【问题标题】:Python perform operation in stringPython在字符串中执行操作
【发布时间】:2013-05-07 19:23:32
【问题描述】:

所以我试图将变量操作(用户定义的)传递给一个函数,并且在尝试找到一种好的方法时遇到了麻烦。我能想到的就是将所有选项硬编码到函数中,如下所示:

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

这一切都很好,一切都很好,但我想知道是否有更好或更有效的方法将条件传递给函数,而无需编写所有可能的 if 语句。有什么想法吗?

解决方案:

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

【问题讨论】:

    标签: python pandas conditional-statements


    【解决方案1】:

    您可以通过operator 模块访问内置运算符,然后构建一个表,将您的运算符名称映射到内置运算符,如下面的简化示例:

    import operator
    ops = {'<=': operator.le, '>=': operator.ge}
    
    In [3]: ops['>='](2, 1)
    Out[3]: True
    

    【讨论】:

    • 这正是我想要的。谢谢。有问题的答案已实施。
    • 虽然这回答了 OP(或在这里绊倒的任何其他人)可以如何做到这一点......他们真的不应该推出他们自己的(效率较低的)numpy 掩码。
    • @AndyHayden:“在这里绊倒的任何其他人”可能没有使用 numpy - 他们可能只是在寻找一种简洁的方法来实现一组运算符。严厉的反对恕我直言。
    • 收回,我仍然认为创建 DSL 来执行此操作的 OP 是个坏主意...
    【解决方案2】:

    你可以使用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
    

    【讨论】:

    • 你将如何在上面的例子中实现这一点?
    • 在 pandas 0.13 中,您将能够通过 query 方法对 DataFrame 对象和 pd.eval 执行 df['legnth == 4 or time == 4'],这是一个使用 numexpr 的顶级评估器引擎盖。
    • @cpcloud 您绝对应该为此添加一个新答案。 :) 非常棒!
    【解决方案3】:

    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__ 都接受任意布尔表达式,并自动在表达式中的每个变量名称上为调用框架实例“添加前缀”(您也可以使用局部变量和全局变量)。这允许您 1) 比在所有内容前面键入 df. 更简洁地表达查询 2) 使用语法表达查询,让我们面对它,看起来比丑陋的按位运算符更好,3) 可能比“纯" 如果你有巨大的框架和一个非常复杂的表达式,则 Python 等效,最后 4) 允许你将相同的查询传递给多个框架(毕竟,它是一个字符串),其中包含一个共同的列子集。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-06
      • 1970-01-01
      • 2013-07-21
      • 1970-01-01
      • 1970-01-01
      • 2016-05-31
      • 2011-10-30
      相关资源
      最近更新 更多