2013-11-04 104 views
4

在pandas中編寫要與groupby.apply或groupby.transform一起使用的函數(如果函數具有多個參數),那麼當將函數作爲groupby的一部分調用時,參數會使用逗號而不是在括號內。一個示例是:使用Groupby調用具有多個參數的函數

def Transfunc(df, arg1, arg2, arg2): 
    return something 

GroupedData.transform(Transfunc, arg1, arg2, arg3) 

其中df參數作爲第一個參數自動傳遞。

但是,使用函數對數據進行分組時似乎不可能使用相同的語法。看看下面的例子:

people = DataFrame(np.random.randn(5, 5), columns=['a', 'b', 'c', 'd', 'e'], index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis']) 
people.ix[2:3, ['b', 'c']] = NA 

def MeanPosition(Ind, df, Column): 
    if df[Column][Ind] >= np.mean(df[Column]): 
     return 'Greater Group' 
    else: 
     return 'Lesser Group' 
# This function compares each data point in column 'a' to the mean of column 'a' and return a group name based on whether it is greater than or less than the mean 

people.groupby(lambda x: MeanPosition(x, people, 'a')).mean() 

上述工作得很好,但我不明白爲什麼我必須包裝功能的拉姆達。基於所使用的語法轉換,並將其應用在我看來,以下應該只是罰款:

people.groupby(MeanPosition, people, 'a').mean() 

誰能告訴我爲什麼,否則我怎麼可以調用函數沒有一個lambda包裝呢?

感謝

編輯:我不認爲這是可能的組通過傳遞一個功能鍵無包裝該功能在拉姆達的數據。一種可能的解決方法是不傳遞函數作爲鍵,而是傳遞一個由函數創建的數組。這將通過以下方式工作:

def MeanPositionList(df, Column): 
    return ['Greater Group' if df[Column][row] >= np.mean(df[Column]) else 'Lesser Group' for row in df.index] 

Grouped = people.groupby(np.array(MeanPositionList(people, 'a'))) 
Grouped.mean() 

但那麼當然它可能只是爲了更好地切出的中間人功能一起,簡單地使用與列表comprhension數組....

+0

我認爲它的設計決策,就可以查詢來源看,如果可能的話(據我所知,它不是),並且如果可以在未來添加'** kwarg'給groupby –

+0

令人沮喪!我的意思是用lambda包裝它很容易,但很難解釋爲什麼這應該是這種情況.... –

回答

3

apply的參數恰好工作,因爲apply將所有參數傳遞給目標函數。

但是,groupby需要多個參數,請參閱here,因此無法區分參數;傳遞一個lambda/named函數更加明確並且要走。

這裏是怎麼做我想你想(略作修改,你必須在你的例子所有不同的羣體)

In [22]: def f(x): 
    ....:  result = Series('Greater',index=x.index) 
    ....:  result[x<x.mean()] = 'Lesser' 
    ....:  return result 
    ....: 

In [25]: df = DataFrame(np.random.randn(5, 5), columns=['a', 'b', 'c', 'd', 'e'], index=['Joe', 'Joe', 'Wes', 'Wes', 'Travis']) 

In [26]: df 
Out[26]: 
       a   b   c   d   e 
Joe -0.293926 1.006531 0.289749 -0.186993 -0.009843 
Joe -0.228721 -0.071503 0.293486 1.126972 -0.808444 
Wes  0.022887 -1.813960 1.195457 0.216040 0.287745 
Wes -1.520738 -0.303487 0.484829 1.644879 1.
Travis -0.061281 -0.517140 0.504645 -1.844633 0.683103 

In [27]: df.groupby(df.index.values).transform(f) 
Out[27]: 
       a  b  c  d  e 
Joe  Lesser Greater Lesser Lesser Greater 
Joe  Greater Lesser Greater Greater Lesser 
Travis Greater Greater Greater Greater Greater 
Wes  Greater Lesser Greater Lesser Lesser 
Wes  Lesser Greater Lesser Greater Greater 
+0

謝謝傑夫。這就是我所設想的,但是我想知道的是,我如何通過上述具有多個參數且沒有lambda表示法的命名函數。寫people.groupby(MeanPosition(people,'a'))會產生一個錯誤,表示參數傳遞不足。如何通過使用lambda表示法的Ind參數?還是不可能? –

+0

我編輯了答案。 grouper函數在索引標籤上被調用,所以它只接受1個參數,理論上你可以使用部分函數。不過,我相信上述解決方案無論如何。 – Jeff

+0

謝謝,實際上這不是我正在尋找的。我編輯了我的問題。我不認爲我想要做的事情可以實現(即調用組函數而不用lambda包裝)。一種解決方法是將密鑰傳遞給本身是由函數創建的數組的組操作。 –

相關問題