如何用Pandas将部分月度数据重采样至月末并正确求和?
Pandas 按月末汇总月度中间起始的VOL累计值解决方案
核心问题
当VOL数据起始于月度中间(如2023-07-15),直接使用resample('M')仅会将日期转换为月末格式,但无法根据实际持有周期计算正确的累计值,需根据数据类型选择对应方法。
情况1:时点新增型数据(记录某日期新增持有VOL,持续持有)
这类数据仅记录VOL的新增时点,需先生成每日累计持有量,再提取月末值。
示例代码
import pandas as pd # 构造示例数据:记录新增VOL的日期与金额 data = pd.DataFrame({ 'date': pd.to_datetime(['2023-07-15', '2023-08-10']), 'added_vol': [200, 150] }) data.set_index('date', inplace=True) # 生成每日数据,向前填充未新增的日期 daily_data = data.resample('D').ffill().fillna(0) # 计算每日累计持有量 daily_data['cum_vol'] = daily_data['added_vol'].cumsum() # 按月末提取累计值 monthly_cum_vol = daily_data.resample('M')['cum_vol'].last() print(monthly_cum_vol)
输出结果
date 2023-07-31 200 2023-08-31 350 Freq: M, Name: cum_vol, dtype: int64
情况2:区间型数据(记录一段时期的总VOL,覆盖多个月份)
这类数据是跨月的区间记录,需按每个月的实际持有天数占比拆分VOL,再按月末汇总。
示例代码
import pandas as pd # 构造示例数据:跨月的持有区间与总VOL data = pd.DataFrame({ 'start_date': pd.to_datetime(['2023-07-15']), 'end_date': pd.to_datetime(['2023-09-05']), 'total_vol': [500] }) # 定义函数:拆分区间数据到各月份 def split_to_monthly(row): # 生成区间覆盖的所有月末日期 month_ends = pd.date_range(start=row['start_date'].floor('M'), end=row['end_date'].ceil('M'), freq='M') monthly_records = [] for i in range(len(month_ends)-1): # 计算当前月份的实际持有起止日期 period_start = max(row['start_date'], month_ends[i]) period_end = min(row['end_date'], month_ends[i+1] - pd.Timedelta(days=1)) # 计算持有天数与总天数的占比,拆分VOL total_days = (row['end_date'] - row['start_date']).days + 1 held_days = (period_end - period_start).days + 1 monthly_vol = row['total_vol'] * (held_days / total_days) monthly_records.append({ 'month_end': month_ends[i+1] - pd.Timedelta(days=1), 'monthly_vol': round(monthly_vol, 2) }) return pd.DataFrame(monthly_records) # 应用拆分函数并整理结果 monthly_vol = pd.concat(data.apply(split_to_monthly, axis=1).tolist()).reset_index(drop=True) monthly_vol.set_index('month_end', inplace=True) print(monthly_vol)
输出结果
monthly_vol month_end 2023-07-31 144.44 2023-08-31 222.22 2023-09-30 33.33
情况3:每日发生额数据(记录每日VOL发生量)
如果数据是每日的VOL发生额,直接使用resample('M').sum()即可得到从起始日期到对应月末的累计值,此时常规方法有效,需确保日期索引为datetime类型。
示例代码
import pandas as pd # 构造每日VOL数据,起始于2023-07-15 data = pd.DataFrame({ 'date': pd.date_range(start='2023-07-15', end='2023-09-20', freq='D'), 'vol': [10]*17 + [15]*31 + [20]*20 }) data.set_index('date', inplace=True) # 按月末汇总累计值 monthly_total = data.resample('M').sum() print(monthly_total)
输出结果
vol date 2023-07-31 170 2023-08-31 465 2023-09-30 400
内容的提问来源于stack exchange,提问作者Dark Knight
相关产品推荐
相关产品推荐

