【问题标题】:In pandas crosstab, how to calculate weighted averages? And how to add row and column totals?在熊猫交叉表中,如何计算加权平均值?以及如何添加行和列总计?
【发布时间】:2020-03-30 01:14:01
【问题描述】:

我有一个 pandas 数据框,其中包含两个分类变量(在我的示例中为城市和颜色),一个包含百分比的列,一个包含权重的列。 我想做一个城市和颜色的交叉表,显示两者的每个组合的 perc 的加权平均值。

我已经设法使用下面的代码来做到这一点,我首先创建一个权重 x perc 的列,然后创建一个带有 (weights x perc) 总和的交叉表,另一个带有权重总和的交叉表,然后最后将一秒一秒。

它有效,但有更快/更优雅的方法吗?

import pandas as pd
import numpy as np
np.random.seed(123)
df=pd.DataFrame()
myrows=10
df['weight'] = np.random.rand(myrows)*100

np.random.seed(321)
df['perc']=np.random.rand(myrows)
df['weight x perc']=df['weight']*df['perc']
df['colour']=np.where( df['perc']<0.5, 'red','yellow')

np.random.seed(555)
df['city']=np.where( np.random.rand(myrows) <0.5,'NY','LA' )


num=pd.crosstab( df['city'], df['colour'], values=df['weight x perc'], aggfunc='sum', margins=True)
den=pd.crosstab( df['city'], df['colour'], values=df['weight'], aggfunc='sum', margins=True)

out=num/den

print(out)

【问题讨论】:

    标签: python pandas crosstab categorical-data


    【解决方案1】:

    这里使用带有 apply() 的 groupby 并使用 numpy 加权平均方法。

    df.groupby(['colour','city']).apply(lambda x: np.average(x.perc, weights=x.weight)).unstack(level=0)
    

    给了

    colour       red    yellow
    city                      
    LA      0.173870  0.865636
    NY      0.077912  0.687400
    

    虽然我没有全部在边缘。

    这将产生总数

    df.groupby(['colour']).apply(lambda x: np.average(x.perc, weights=x.weight))
    df.groupby(['city']).apply(lambda x: np.average(x.perc, weights=x.weight))
    

    授予仍然没有打包到单个框架中

    【讨论】:

    • 谢谢。我需要总数,所以我的方法可能更容易。
    【解决方案2】:

    我遇到了同样的问题。我现在找到了解决方案!是的! 我是编程初学者,我的代码可以运行,但可以改进,这是肯定的。 我希望它可以帮助某人。 谢谢大家的帮助。

    import pandas as pd
    import numpy as np
    
    np.random.seed(123)
    df=pd.DataFrame()
    myrows=10
    df['weight'] = np.random.rand(myrows)*100
    
    np.random.seed(321)
    df['perc']=np.random.rand(myrows)
    #df['weight x perc']=df['weight']*df['perc']
    df['colour']=np.where( df['perc']<0.5, 'red','yellow')
    
    np.random.seed(555)
    df['city']=np.where( np.random.rand(myrows) <0.5,'NY','LA' )
    
    df.head()
    

    和标签创建:

    grouped = df.groupby(['colour','city'])
    ci = df.groupby('city')
    co =df.groupby('colour')
    
    def wavg(group):
        d = group['perc']
        w = group['weight']
        return (d * w).sum() / w.sum()
    
    # adding 1 columns of aggregate the weighted average by row
    result = pd.concat([grouped.apply(wavg).unstack(level=0),ci.apply(wavg).rename('weighted average')],axis = 1)
    # change index because unstack get city is index, i want city in columns
    result.index.name='city'
    result.reset_index(inplace=True)
    # adding 1 row in bottom of aggregate the weighted average by columns and weighted average of the dataframe (total)
    # be careful about co.ndim i'm not sure is alway ok
    result.loc['WAvg'] = ['weighted average'] + [co.apply(wavg).values.round(1)[i] for i in range(0,co.ndim)] + [((df['perc'] * df['weight']).sum() / df['weight'].sum()).round(1)] 
    result
    

    查看结果:

    I had this result

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-04
      • 1970-01-01
      • 2022-01-06
      • 2014-11-30
      • 1970-01-01
      相关资源
      最近更新 更多