Python在字符串中执行操作
所以我试图将一个变量操作(用户定义的)传递给一个函数,并且在试图找到一个好的方法时遇到了困难。所有我能想到的做的是硬编码的所有选项进入的功能等以下几点:Python在字符串中执行操作
def DoThings(Conditions):
import re
import pandas as pd
d = {'time' : pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd']),
'legnth' : pd.Series([4., 5., 6., 7.], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
print df
for Condition in Conditions:
# Split the condition into two parts
SplitCondition = re.split('<=|>=|!=|<|>|=',Condition)
# If the right side of the conditional statement is a number convert it to a float
if SplitCondition[1].isdigit():
SplitCondition[1] = float(SplitCondition[1])
# Perform the condition specified
if "<=" in Condition:
df = df[df[SplitCondition[0]]<=SplitCondition[1]]
print "one"
elif ">=" in Condition:
df = df[df[SplitCondition[0]]>=SplitCondition[1]]
print "two"
elif "!=" in Condition:
df = df[df[SplitCondition[0]]!=SplitCondition[1]]
print "three"
elif "<" in Condition:
df = df[df[SplitCondition[0]]<=SplitCondition[1]]
print "four"
elif ">" in Condition:
df = df[df[SplitCondition[0]]>=SplitCondition[1]]
print "five"
elif "=" in Condition:
df = df[df[SplitCondition[0]]==SplitCondition[1]]
print "six"
return df
# Specify the conditions
Conditions = ["time>2","legnth<=6"]
df = DoThings(Conditions) # Call the function
print df
导致此:
legnth time
a 4 1
b 5 2
c 6 3
d 7 4
five
one
legnth time
c 6 3
这是一切都很好,一切,但我不知道是否有一种更好或更有效的方式将条件传递给函数,而不用写出所有可能的语句。有任何想法吗?
SOLUTION:
def DoThings(Conditions):
import re
import pandas as pd
d = {'time' : pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd']),
'legnth' : pd.Series([4., 5., 6., 7.], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
print df
for Condition in Conditions:
# Split the condition into two parts
SplitCondition = re.split('<=|>=|!=|<|>|=',Condition)
# If the right side of the conditional statement is a number convert it to a float
if SplitCondition[1].isdigit():
SplitCondition[1] = float(SplitCondition[1])
import operator
ops = {'<=': operator.le, '>=': operator.ge, '!=': operator.ne, '<': operator.lt, '>': operator.gt, '=': operator.eq}
cond = re.findall(r'<=|>=|!=|<|>|=', Condition)
df = df[ops[cond[0]](df[SplitCondition[0]],SplitCondition[1])]
return df
# Specify the conditions
Conditions = ["time>2","legnth<=6"]
df = DoThings(Conditions) # Call the function
print df
输出:
legnth time
a 4 1
b 5 2
c 6 3
d 7 4
legnth time
c 6 3
您可以通过operator
模块访问内置的运营商,再建一个表映射您的运营商名称的内置在这个例子中,就像这个简单的例子:
import operator
ops = {'<=': operator.le, '>=': operator.ge}
In [3]: ops['>='](2, 1)
Out[3]: True
您可以使用masking做这种操作的(你会发现这是一个很多更快):
In [21]: df[(df.legnth <= 6) & (df.time > 2)]
Out[21]:
legnth time
c 6 3
In [22]: df[(df.legnth <= 6) & (df.time >= 2)]
Out[22]:
legnth time
b 5 2
c 6 3
注:我们在您的实现中的错误,由于B不应该包括在查询。
你也可以做或(使用|
)操作,其工作如你所愿:
In [23]: df[(df.legnth == 4) | (df.time == 4)]
Out[23]:
legnth time
a 4 1
d 7 4
并且您将如何在上面的示例中实现此操作? – 2013-05-14 18:11:43
在pandas 0.13中,您可以在'DataFrame'对象的'query'方法上''df ['legnth == 4或time == 4']'顶部级别的'pd.eval'评估者在引擎盖下使用'numexpr'。 – 2013-07-27 21:54:36
@cpcloud你应该明确地添加一个新的答案。 :) 太棒了! – 2013-07-28 05:13:14
在pandas==0.13
(不知道什么时候发布的,这将是... 0.12
刚出来的时候)你就可以做到以下几点,所有这些都是等价的:
res = df.query('(legnth == 4) | (time == 4)')
res = df.query('legnth == 4 | time == 4')
res = df.query('legnth == 4 or time == 4')
和我个人最喜欢的
res = df['legnth == 4 or time == 4']
query
和__getitem__
都接受一个任意的布尔表达式,并且自动为表达式中的每个变量名(也可以使用locals和globals)调用框架实例“前缀”。这使您可以1)比在所有内容前面输入df.
更简洁地表达查询2)使用语法表达查询,让我们面对它,看起来比丑陋的按位运算符好3)可能比“纯”Python快得多如果你有巨大的框架和一个非常复杂的表达式,等价的,最后4)允许你将同一个查询传递给多个框架(毕竟,它是一个字符串)与列的一个共同的子集。
这正是我一直在寻找的。谢谢。回答有问题。 – 2013-05-13 22:54:53
虽然这回答了OP(或任何其他人在这里绊倒)如何做到这一点......他们真的不应该推出他们自己的(效率较低)numpy屏蔽。 – 2013-05-14 01:53:33
@AndyHayden:“任何人在这里都有绊脚石”可能不会使用numpy--他们可能只是寻找一种简洁的方式来实现一组运算符。苛刻downvote恕我直言。 – RichieHindle 2013-05-14 07:02:58