Pandas分组后ffill跨组填充致收益率计算异常的问题及解决
分钟K线收益率计算的分组填充问题
我用以下代码计算分钟K线收益率:
df = df.query('Time >= @start_time and Time < @end_time') df.loc[:, 'date'] = pd.to_datetime(df['date']) df['ret'] = (df.groupby(['date', 'sym'])['Close'] .ffill() .pct_change())
执行后发现,每个groupby(['date', 'sym'])分组的ret列第一行并非预期的NaN,而是一个不符合分钟K线逻辑的异常大数值。推测是pandas的ffill()在不同分组间发生了跨组填充,但一开始找不到解决方法。
我的DataFrame包含date、sym、Time、Close列,预期的ret列结果如下:
| 索引 | 数值 |
|---|---|
| 30986938 | NaN |
| 30986939 | 0.000934 |
| 30986940 | 0.001386 |
| 30986941 | -0.000461 |
| 30986942 | 0.000462 |
| 30986943 | -0.000180 |
| 30986944 | 0.000180 |
但实际得到的ret列结果为:
| 索引 | 数值 |
|---|---|
| 30986938 | -0.148827 |
| 30986939 | 0.000934 |
| 30986940 | 0.001386 |
| 30986941 | -0.000461 |
| 30986942 | 0.000462 |
| 30986943 | -0.000180 |
| 30986944 | 0.000180 |
我尝试过使用apply/transform(lambda x: x.ffill()),或者groupby(, as_index=False),但都无法解决问题。最终找到正确的写法:
df['ret'] = df.groupby(['date', 'sym'])['Close'].apply(lambda x: x.ffill().pct_change())
问题原因说明
原代码中,groupby(['date', 'sym'])['Close'].ffill()会返回保留原DataFrame索引的Series,后续调用pct_change()时,会基于全局索引的前一行值计算,而非分组内的前一行。而用apply将ffill()和pct_change()封装在同一个分组逻辑中,能确保每个分组内先完成向前填充,再计算涨跌幅,分组第一行因无前置数据自然得到NaN,符合预期。
内容的提问来源于stack exchange,提问作者Xiangyang Yang
相关产品推荐
相关产品推荐

