2013-05-13 82 views
1

所以我試圖將一個變量操作(用戶定義的)傳遞給一個函數,並且在試圖找到一個好的方法時遇到了困難。所有我能想到的做的是硬編碼的所有選項進入的功能等以下幾點: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 

回答

4

您可以通過operator模塊訪問內置的運營商,再建一個表映射您的運營商名稱的內置在這個例子中,就像這個簡單的例子:

import operator 
ops = {'<=': operator.le, '>=': operator.ge} 

In [3]: ops['>='](2, 1) 
Out[3]: True 
+0

這正是我一直在尋找的。謝謝。回答有問題。 – 2013-05-13 22:54:53

+0

雖然這回答了OP(或任何其他人在這裏絆倒)如何做到這一點......他們真的不應該推出他們自己的(效率較低)numpy屏蔽。 – 2013-05-14 01:53:33

+0

@AndyHayden:「任何人在這裏都有絆腳石」可能不會使用numpy--他們可能只是尋找一種簡潔的方式來實現一組運算符。苛刻downvote恕我直言。 – RichieHindle 2013-05-14 07:02:58

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 
+0

並且您將如何在上面的示例中實現此操作? – 2013-05-14 18:11:43

+0

在pandas 0.13中,您可以在'DataFrame'對象的'query'方法上''df ['legnth == 4或time == 4']'頂部級別的'pd.eval'評估者在引擎蓋下使用'numexpr'。 – 2013-07-27 21:54:36

+0

@cpcloud你應該明確地添加一個新的答案。 :) 太棒了! – 2013-07-28 05:13:14

0

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)允許你將同一個查詢傳遞給多個框架(畢竟,它是一個字符串)與列的一個共同的子集。