2014-10-05 129 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)