首页 > 解决方案 > 面板数据中的熊猫时间加权平均分组比

问题描述

嗨我有一个面板数据集看起来像

stock    date     time   spread1  weight  spread2 
VOD      01-01    9:05    0.01    0.03     ...
VOD      01-01    9.12    0.03    0.05     ...
VOD      01-01   10.04    0.02    0.30     ...
VOD      01-02   11.04    0.02    0.05
...       ...     ...     ....     ...
BAT      01-01   0.05     0.04    0.03
BAT      01-01   0.07     0.05    0.03
BAT      01-01   0.10     0.06    0.04

我想计算spread1每天每只股票的加权平均值。我可以将解决方案分为几个步骤。即我可以应用函数来获取dataframe1中每天每只股票的spread1*weight之和,然后计算dataframe2中每天每只股票的权重之和groupbyagg之后merge两个数据集并获得spread1的加权平均值。

我的问题是有什么简单的方法来计算 spread1 的加权平均值吗?我也有spread2、spread3和spread4。所以我想写尽可能少的代码。谢谢

标签: pandaspandas-groupbyweighted-average

解决方案


IIUC,您需要transform将结果恢复为原始结果,但是使用.transform依赖于两列的输出很棘手。我们编写自己的函数,在其中传递一系列展开s和原始 DataFrame df,因此我们也可以使用权重:

import numpy as np

def weighted_avg(s, df):
    return np.average(s, weights=df.loc[df.index.isin(s.index), 'weight'])

df['spread1_avg'] = df.groupby(['stock', 'date']).spread1.transform(weighted_avg, df)

输出:

  stock   date   time  spread1  weight  spread1_avg
0   VOD  01-01   9:05     0.01    0.03     0.020526
1   VOD  01-01   9.12     0.03    0.05     0.020526
2   VOD  01-01  10.04     0.02    0.30     0.020526
3   VOD  01-02  11.04     0.02    0.05     0.020000
4   BAT  01-01   0.05     0.04    0.03     0.051000
5   BAT  01-01   0.07     0.05    0.03     0.051000
6   BAT  01-01   0.10     0.06    0.04     0.051000

如果需要多列:

gp = df.groupby(['stock', 'date'])
for col in [f'spread{i}' for i in range(1,5)]:
    df[f'{col}_avg'] = gp[col].transform(weighted_avg, df)

或者,如果您不需要转换回来并且想要每个股票日期的价值:

def my_avg2(gp):
    avg = np.average(gp.filter(like='spread'), weights=gp.weight, axis=0)
    return pd.Series(avg, index=[col for col in gp.columns if col.startswith('spread')])    

### Create some dummy data
df['spread2'] = df.spread1+1
df['spread3'] = df.spread1+12.1
df['spread4'] = df.spread1+1.13

df.groupby(['stock', 'date'])[['weight'] + [f'spread{i}' for i in range(1,5)]].apply(my_avg2)

#              spread1   spread2    spread3   spread4
#stock date                                          
#BAT   01-01  0.051000  1.051000  12.151000  1.181000
#VOD   01-01  0.020526  1.020526  12.120526  1.150526
#      01-02  0.020000  1.020000  12.120000  1.150000

推荐阅读