2014-10-05 201 views
19

我有下表。我想根據下面的公式計算每個日期分組的加權平均值。我可以使用一些標準的常規代碼來做到這一點,但假設這些數據是在熊貓數據框中,是否有更簡單的方法來實現這一點,而不是通過迭代?使用熊貓/數據框計算加權平均值

Date  ID  wt  value w_avg 
01/01/2012 100  0.50 60  0.791666667 
01/01/2012 101  0.75 80 
01/01/2012 102  1.00 100 
01/02/2012 201  0.50 100  0.722222222 
01/02/2012 202  1.00 80 

01/01/2012 w_avg = 0.5 *(60 /總和(60,80,100))+ 0.75 *(80 /總和(60,80,100))+ 1.0 *(100 /和(60, 80100))

01/02/2012 w_avg = 0.5 *(100 /和(100,80))+ 1.0 *(80 /總和(100,80))

+3

注,在您的例子中,「價值」列實際上代表的權重,和「重量」列值的平均值... – kadee 2015-10-10 13:09:52

回答

17

我認爲將與這樣做兩個groupbys。

首先計算出「加權平均」:

In [11]: g = df.groupby('Date') 

In [12]: df.value/g.value.transform("sum") * df.wt 
Out[12]: 
0 0.125000 
1 0.250000 
2 0.416667 
3 0.277778 
4 0.444444 
dtype: float64 

如果設置此爲一列,您可以通過它GROUPBY:

In [13]: df['wa'] = df.value/g.value.transform("sum") * df.wt 

現在這列的總和是期望:

In [14]: g.wa.sum() 
Out[14]: 
Date 
01/01/2012 0.791667 
01/02/2012 0.722222 
Name: wa, dtype: float64 

或潛在:

In [15]: g.wa.transform("sum") 
Out[15]: 
0 0.791667 
1 0.791667 
2 0.791667 
3 0.722222 
4 0.722222 
Name: wa, dtype: float64 
+0

注意:我不是100%,當我改變df的時候,我覺得重用g,只要你沒有改變組的密鑰,我認爲它很整潔......可能這是有爭議的? IMO pandastic。 – 2014-10-05 19:59:12

+0

我能夠做到這一點做類似的事情,但不是變換,我只是使用groupby(..)。sum()。使用變換有什麼好處嗎? – mike01010 2014-10-05 20:25:58

+0

@AndyHayden DataFrameGroupBy對象*會*反映一個變異的對象,但在這種情況下,你不會變異,所以沒什麼大不了的。 – Jeff 2014-10-05 20:44:59

11

讓我們首先創建示例大熊貓數據幀:

In [1]: import numpy as np 

In [2]: import pandas as pd 

In [3]: index = pd.Index(['01/01/2012','01/01/2012','01/01/2012','01/02/2012','01/02/2012'], name='Date') 

In [4]: df = pd.DataFrame({'ID':[100,101,102,201,202],'wt':[.5,.75,1,.5,1],'value':[60,80,100,100,80]},index=index) 

然後,獲得作爲「重量」通過「價值」加權和由索引分組的平均:

In [5]: df.groupby(df.index).apply(lambda x: np.average(x.wt, weights=x.value)) 
Out[5]: 
Date 
01/01/2012 0.791667 
01/02/2012 0.722222 
dtype: float64 

替代地,還可以定義一個功能:

In [5]: def grouped_weighted_avg(values, weights, by): 
    ...:  return (values * weights).groupby(by).sum()/weights.groupby(by).sum() 

In [6]: grouped_weighted_avg(values=df.wt, weights=df.value, by=df.index) 
Out[6]: 
Date 
01/01/2012 0.791667 
01/02/2012 0.722222 
dtype: float64 
+0

我喜歡這個更好(由於可讀性),這和Andy Hayden的解決方案之間有什麼顯着的表現嗎? – erb 2015-10-19 11:47:27

+2

有沒有可能在這一行: In [5]:df.groupby(df.index).apply(lambda x:np.average(x.wt,weights = x.value)) x.wt和x.value應該切換? – prooffreader 2016-02-09 15:49:37

+0

@prooffreader:正如我評論[上述](http://stackoverflow.com/questions/26205922/calculate-weighted-average-using-a-pandas-dataframe/33054358#comment53928794_26205922):在由提問者給出的例子中, '值'列實際上代表權重,'wt'列代表要被平均的值。 – kadee 2016-04-12 10:02:43

5

我.csv文件保存表

df=pd.read_csv('book1.csv') 

grouped=df.groupby('Date') 
g_wavg= lambda x: np.average(x.wt, weights=x.value) 
grouped.apply(g_wavg)