Groupby和加权平均值

时间:2017-11-08 16:12:46

标签: python pandas

我有一个数据框:

import pandas as pd
import numpy as np

df=pd.DataFrame.from_items([('STAND_ID',[1,1,2,3,3,3]),('Species',['Conifer','Broadleaves','Conifer','Broadleaves','Conifer','Conifer']),
                             ('Height',[20,19,13,24,25,18]),('Stems',[1500,2000,1000,1200,1700,1000]),('Volume',[200,100,300,50,100,10])])

   STAND_ID      Species  Height  Stems  Volume
0         1      Conifer      20   1500     200
1         1  Broadleaves      19   2000     100
2         2      Conifer      13   1000     300
3         3  Broadleaves      24   1200      50
4         3      Conifer      25   1700     100
5         3      Conifer      18   1000      10

我希望按STAND_ID和Species进行分组,对高度和词干应用加权平均值,并将体积作为权重并取消叠加。

所以我试试:

newdf=df.groupby(['STAND_ID','Species']).agg({'Height':lambda x: np.average(x['Height'],weights=x['Volume']),
                                              'Stems':lambda x: np.average(x['Stems'],weights=x['Volume'])}).unstack()

哪个给我错误:

  

builtins.KeyError:'高度'

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

您的错误是因为您无法使用agg执行多个系列/列操作。 Agg作为一个时间采用一个系列/列。我们使用applypd.concat

g = df.groupby(['STAND_ID','Species'])
newdf = pd.concat([g.apply(lambda x: np.average(x['Height'],weights=x['Volume'])), 
                   g.apply(lambda x: np.average(x['Stems'],weights=x['Volume']))], 
                   axis=1, keys=['Height','Stems']).unstack()

编辑更好的解决方案:

g = df.groupby(['STAND_ID','Species'])
newdf = g.apply(lambda x: pd.Series([np.average(x['Height'], weights=x['Volume']), 
                             np.average(x['Stems'],weights=x['Volume'])], 
                                    index=['Height','Stems'])).unstack()

输出:

              Height                  Stems             
Species  Broadleaves    Conifer Broadleaves      Conifer
STAND_ID                                                
1               19.0  20.000000      2000.0  1500.000000
2                NaN  13.000000         NaN  1000.000000
3               24.0  24.363636      1200.0  1636.363636