大熊猫时间加权平均组合在面板数据中

问题描述 投票:0回答:1

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

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

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

pandas pandas-groupby weighted-average
1个回答
1
投票

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)

Output:

  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
© www.soinside.com 2019 - 2024. All rights reserved.