如何在Pandas中添加3天后Close值的滚动列(无循环实现)
问题描述
我有一个包含Date、Open、High、Low、Close字段的股票Pandas DataFrame,数据如下:
| Date | Open | High | Low | Close |
|---|---|---|---|---|
| 2019-12-30 | 216 | 221 | 213 | 220 |
| 2019-12-31 | 241 | 250 | 229 | 243 |
| 2020-01-01 | 239 | 242 | 217 | 229 |
| 2020-01-02 | 244 | 252 | 234 | 249 |
希望在Pandas中新增一列Rolling,该列展示每行日期3天后的Close值(用于计算3日收益率),预期效果如下:
| Date | Open | High | Low | Close | Rolling | 说明 |
|---|---|---|---|---|---|---|
| 2019-12-30 | 216 | 221 | 213 | 220 | 249 | 对应2020-01-02的Close值(3天后) |
| 2019-12-31 | 241 | 250 | 229 | 243 | 252 | 对应2020-01-03的Close值(3天后) |
| 2020-01-01 | 239 | 242 | 217 | 229 | 对应2020-01-04的Close值(无数据则空) | |
| 2020-01-02 | 244 | 252 | 234 | 249 | 对应2020-01-05的Close值(无数据则空) | |
| 2020-01-03 | 249 | 256 | 244 | 252 | 对应2020-01-06的Close值(无数据则空) |
要求提供无需使用for循环的实现方案。
实现方案
场景1:连续交易日数据(无缺失)
如果股票数据按连续交易日排列(无周末/节假日缺失),直接使用shift方法即可高效实现:
import pandas as pd # 确保Date列为日期类型 df['Date'] = pd.to_datetime(df['Date']) # 新增Rolling列,取当前行之后第3行的Close值 df['Rolling'] = df['Close'].shift(-3)
场景2:严格按自然日偏移(含非交易日)
如果需要严格匹配自然日3天后的Close值(不管中间是否有交易日),按以下步骤实现:
import pandas as pd # 1. 转换Date列为日期类型并设为索引 df['Date'] = pd.to_datetime(df['Date']) df = df.set_index('Date') # 2. 生成包含所有自然日的序列(从数据最小日期到最大日期+3天) full_date_range = pd.date_range( start=df.index.min(), end=df.index.max() + pd.Timedelta(days=3) ) # 3. 重新索引补全所有日期,缺失的Close值填充为NaN full_df = df.reindex(full_date_range) # 4. 偏移3天获取对应Close值 full_df['Rolling'] = full_df['Close'].shift(-3) # 5. 还原回原始数据的日期并重置索引 df = full_df.loc[df.index].reset_index().rename(columns={'index': 'Date'})
关键说明
shift(-3)是Pandas内置的向量化操作,完全避免了for循环,执行效率远高于循环遍历。- 连续交易日场景下,
shift(-3)直接对应3个交易日后的Close值;自然日场景下,通过补全日期序列确保严格匹配3天后的日期。
内容的提问来源于stack exchange,提问作者Moxarth Oswal
相关产品推荐
相关产品推荐

