2017-01-02 50 views
2

我有以下DataFrames:熊貓 - 的Python:應用(),並且如果/則的邏輯

example = pd.DataFrame({"dirr":[1,0,-1,-1,1,-1,0], 
         "value": [125,130,80,8,150,251,18], 
         "result":[np.NaN for _ in range(7)]}) 

我想執行與芹菜()和cummax(以下操作)就可以了:

example["result"].apply(lambda x : x= example["value"].cummax() if example["dirr"]==1 
          else x= example["value"].cummin() if example["dirr"]==-1 
          else x= NaN if if example["dirr"]==0 
          ) 

這是返回:error: invalid syntax

任何人都可以幫我理清那個嗎?

這將是預期的輸出:

example = pd.DataFrame({"dirr":[1,0,-1,-1,1,-1,0], 
         "value": [125,130,80,8,150,251,18], 
         "result":[125, NaN, 80, 8, 150, 8, NaN]}) 

編輯:

所以爲每@ su79eu7k以下功能的答案會做:

def calc(x): 
    if x['dirr'] == 1: 
     return np.diag(example["value"].cummax()) 
    elif x['dirr'] == -1: 
     return np.diag(example["value"].cummin()) 
    else: 
     return np.nan 

我應該能夠把它推入lambda,但仍然在語法錯誤上被阻止......我仍然看不到?

example["result"]=example.apply(lambda x : np.diag(x["value"].cummax()) if x["dirr"]==1 
           else np.diag(x["value"].cummin()) if x["dirr"]==-1 
           else NaN if x["dirr"]==0 
          ) 

最後一點小推動形式,你們將非常感激。

+0

如果結果是'[125, NaN,125,80 ,150,8,NaN]或[125,NaN,80,8,150,8,NaN] – 3novak

+0

@ 3novak:是的,你說得對。編輯 –

回答

2

我認爲@ 3novak的解決方案簡單快捷。但是,如果你真的想用apply功能,

def calc(x): 
    if x['dirr'] == 1: 
     return example["value"].cummax() 
    elif x['dirr'] == -1: 
     return example["value"].cummin() 
    else: 
     return np.nan 

example['result'] = np.diag(example.apply(calc, axis=1)) 

print example 

    dirr result value 
0  1 125.0 125 
1  0  NaN 130 
2 -1 80.0  80 
3 -1  8.0  8 
4  1 150.0 150 
5 -1  8.0 251 
6  0  NaN  18 
+0

謝謝你,這是非常有趣的:從我看到你創建的函數本質上與我在我的問題中提到的函數相同,除了兩件事:1)語法的作品!爲什麼它不適用於我的問題?(我嘗試用'elif'替換第二個'else',但仍然有錯誤)。 2)np.diag()函數。它究竟做了什麼?理想情況下,我想保留我的原始lambda函數。我認爲3行是好的,它使代碼更清晰。 –

+0

https://google.github.io/styleguide/pyguide.html?showone=Lambda_Functions#Lambda_Functions和http://stackoverflow.com/questions/14029245/python-putting-an-if-elif-else-statement-on一行解決所需lambda的缺點和不可能性。 – 3novak

+0

@ su79eu7k:好吧,我明白了,我不能在lambda中的if/else中使用*語句*。關於我的第二個問題,有什麼'numpy.diag()'函數?爲什麼它不只是'example ['result'] = example.apply(calc,axis = 1)' –

2

我認爲使用單獨的行代替應用是最有意義的。如果你確實使用了apply函數,你應該創建一個單獨的函數並傳遞它,而不是製作一個三行lambda。

example.loc[example['dirr'] == 1, 'result'] = \ 
      example.loc[example['dirr'] == 1, 'value'].cummax() 
example.loc[example['dirr'] == -1, 'result'] = \ 
      example.loc[example['dirr'] == -1, 'value'].cummin() 

>>> example 
    dirr result value 
0  1 125.0 125 
1  0  NaN 130 
2 -1 80.0  80 
3 -1  8.0  8 
4  1 150.0 150 
5 -1  8.0 251 
6  0  NaN  18 

替代apply方法如下。

current_max = 0 
current_min = 9999 

def func(df): 
    global current_max 
    global current_min 
    if df['dirr'] == 1: 
     current_max = max(current_max, df['value']) 
     return current_max 
    elif df['dirr'] == -1: 
     current_min = min(current_min, df['value']) 
     return current_min 
    else: 
     return np.nan 

example['result'] = example.apply(func, axis=1) 
+0

Thx爲您的答覆,它確實有效。然而我真的不明白這個邏輯:你傳遞一個布爾表作爲位置參數?如果你想讓它成爲一個函數並通過apply()方法傳遞,你將如何去做? –

+0

正確的話,我們對要分配的數據幀的部分進行索引,然後對影響返回數據的部分的數據幀進行子集化。我已經編輯了我的帖子以供替代應用函數使用,但全局變量使它變得有點鬆動。 – 3novak

+0

我可以用Pandas.mask()來做同樣的事情。這是我用來擁有的。但我不喜歡的語法,並希望在1行中定義「結果」值。 –

0

所有numpy的

v = example.value.values 
d = example.dirr.values 
mx = np.maximum.accumulate(v) 
mn = np.minimum.accumulate(v) 
example['result'] = np.where(d == 1, mx, np.where(d == -1, mn, np.nan)) 
example 

    dirr result value 
0  1 125.0 125 
1  0  NaN 130 
2 -1 80.0  80 
3 -1  8.0  8 
4  1 150.0 150 
5 -1  8.0 251 
6  0  NaN  18 

時機

enter image description here