如何用Pandas计算多数据点指定日期区间收益率并保留目标日期
解决方案
你的问题出在排序方向和pct_change()的计算逻辑上:你按日期降序排列后,pct_change()会把后一行(1月数据)和前一行(2月数据)的比值结果放到1月的行里,完全搞反了对应关系。
下面是两种直接解决问题的方法:
方法1:先聚合月度价格再合并
这种方法先提取每个标的1月和2月的最终价格,计算收益率后再关联回2月的原始数据行。
import pandas as pd # 确保日期列是datetime类型 df['Date'] = pd.to_datetime(df['Date']) # 筛选2023年1-2月的数据 df_filtered = df[(df['Date'].dt.year == 2023) & (df['Date'].dt.month.isin([1, 2]))] # 按标的和月份聚合,取每个月最后一天的价格 monthly_prices = df_filtered.groupby( ['Identifier', df_filtered['Date'].dt.month] )['Price'].last().unstack() # 把月份转成列 # 计算收益率:(2月价格/1月价格)-1 monthly_prices['Returns'] = (monthly_prices[2] / monthly_prices[1]) - 1 # 合并收益率到2月的原始数据行 result = df_filtered[df_filtered['Date'].dt.month == 2].merge( monthly_prices[['Returns']].reset_index(), on='Identifier', how='left' )
方法2:直接在原始数据中计算
这种方法在排序后的数据集里,通过分组提取每个标的的1月价格,直接计算2月行的收益率。
import pandas as pd # 确保日期列是datetime类型 df['Date'] = pd.to_datetime(df['Date']) # 筛选2023年1-2月的数据并按标的、日期升序排列 df_sorted = df[ (df['Date'].dt.year == 2023) & (df['Date'].dt.month.isin([1, 2])) ].sort_values(['Identifier', 'Date']) # 分组提取每个标的1月的最终价格 df_sorted['Jan_Price'] = df_sorted.groupby('Identifier')['Price'].transform( lambda x: x[x.index.month == 1].iloc[-1] if any(x.index.month == 1) else None ) # 计算收益率 df_sorted['Returns'] = (df_sorted['Price'] / df_sorted['Jan_Price']) - 1 # 仅保留2月的数据行,移除临时列 result = df_sorted[df_sorted['Date'].dt.month == 2].drop('Jan_Price', axis=1)
为什么你的原代码不符合预期?
原代码按Identifier和Date降序排列后,groupby('Identifier').Price.pct_change()会计算当前行价格 / 前一行价格 - 1。此时每个组的第一行是2月数据,第二行是1月数据,所以计算出的是(1月价格/2月价格)-1,并且结果被赋值给1月的行,完全和你需要的"2月行对应(2月/1月)-1"的逻辑相反。
内容的提问来源于stack exchange,提问作者Kronivar
相关产品推荐
相关产品推荐

