2017-06-22 12 views
1

讓我們假設,我們給出以下功能:應用lambda函數使用更新的值

def f(x,y): 
    y = x + y 
    return y 

功能f(x,y)總結兩個數字(但它可能是兩個參數的任何或多或少複雜的功能)。現在讓我們看看下面的

import pandas as pd 
import random 
import numpy as np 

random.seed(1234) 
df = pd.DataFrame({'first': random.sample(range(0, 9), 5), 
        'second': np.NaN}, index = None) 
y = 1 

df 
    first second 
0  7  NaN 
1  1  NaN 
2  0  NaN 
3  6  NaN 
4  4  NaN 

的提問數據幀的第二列是在這裏無關緊要的範圍,所以我們可以不失一般性假設要NaN。考慮到變量y已被初始化爲1,讓我們對數據幀的每一行應用f(x,y)。第一次迭代返回7 + 1 = 8;現在,再次將函數應用於第二行時,我們希望y值更新爲先前計算的8,因此最終結果爲1 + 8 = 9,依此類推。

什麼是pythonic方式來處理這個?我想避免循環和重新分配循環內的變量,因此,我的猜測是沿

def apply_to_df(df, y): 
    result = df['first'].apply(lambda s: f(s,y)) 
    return result 

線的東西但是人們可以很容易地看到,上述不考慮更新的值,而它計算所有計算初始值爲y=1

print(apply_to_df(df,y)) 
0 8 
1 2 
2 1 
3 7 
4 5 
+0

什麼你所描述的是一個遞推關係。雖然已經討論過,並且有一個關於它的開放(但是老的)[問題](https://github.com/pandas-dev/pandas/issues/4567),但在熊貓中沒有內建的方法。 。現在,你必須循環才能做到這一點。 – BrenBarn

+0

這不是cumsum(),還是更一般的減少? – jeremycg

+0

在這種情況下,它看起來是:'df ['first']。cumsum()+ y0',其中'y0'是y的初始種子值(本例中爲1)。 – Alexander

回答

1

注意,你或許可以解決這個具體情況下,與現有的累計功能。然而,在一般情況下,你可以只依靠全局狀態本事:

In [7]: y = 1 

In [8]: def f(x): 
    ...:  global y 
    ...:  y = x + y 
    ...:  return y 
    ...: 

In [9]: df['first'].apply(lambda s: f(s)) 
Out[9]: 
0  8 
1  9 
2  9 
3 15 
4 19 
Name: first, dtype: int64 

我想避免循環

注意,pd.DataFrame.apply內循環和重新分配變量引擎蓋下的一個香草Python循環,實際上效率較低,因爲它對輸入進行了大量檢查/驗證。這並不意味着高效,但方便。所以,如果你關心性能,你已經放棄了,如果你是靠.apply

老實說,我認爲我寧願寫在行的顯式循環不是依賴於全局狀態的函數內。

+0

全局變量的訣竅實際上起作用,雖然正如你所提到的那樣,我會考慮讓整個循環更加明確。 – gented

0

你可以使用一個發電機功能記住先前計算結果:

def my_generator(series, foo, y_seed=0): 
    y = y_seed # Seed value for `y`. 
    s = series.__iter__() # Create an iterator on the series. 
    while True: 
     # Call the function on the next `x` value together with the most recent `y` value. 
     y = foo(x=s.next(), y=y) 
     yield y 

df = df.assign(new_col=list(my_generator(series=df['first'], foo=f, y_seed=1))) 
>>> df 
    first second new_col 
0  8  NaN  9 
1  3  NaN  12 
2  0  NaN  12 
3  5  NaN  17 
4  4  NaN  21