You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多索引DataFrame按BM频率重采样:后续日期缺失问题求助

解决多索引DataFrame按BM重采样时缺失后续日期的问题

你的问题根源在于:groupby('id').resample('BM') 会基于每个id自身的时间范围生成重采样索引——也就是说,每个id只在自己有数据的时间段内生成BM日期,一旦过了该id最后一条非NaN数据的日期,就不会继续生成后续日期。

要让所有id都延续到统一的结束日期,你需要先定义全局的BM时间序列,再让每个id对齐这个序列。下面是两种可行的实现方式:

方法一:先拆堆再重采样(更高效)

  1. 首先确定你需要的全局时间范围:可以取整个数据集的最早BM日期,再手动指定结束日期(比如你想要到2024年12月的最后一个工作日)
  2. 把多索引DataFrame拆成宽表(id为列),对齐全局时间序列后再恢复成多索引
import pandas as pd

# 假设你的原DataFrame是多索引:df.index = pd.MultiIndex.from_tuples([(date, id), ...], names=['date', 'id'])
# 步骤1:定义全局BM时间序列
# 取整个数据集的最早日期,转成BM格式
start_bm = df.index.get_level_values('date').min().to_period('BM').start_time
# 手动指定结束日期(比如2024年12月的最后一个工作日)
end_bm = pd.to_datetime('2024-12-31').to_period('BM').start_time
# 生成完整的BM日期序列
full_bm_dates = pd.date_range(start=start_bm, end=end_bm, freq='BM')

# 步骤2:拆成宽表并对齐全局日期
df_wide = df.unstack(level='id')  # 把id转成列,date作为索引
# 重采样对齐全局日期,保留BM频率
df_resampled_wide = df_wide.reindex(full_bm_dates).asfreq('BM')

# 步骤3:恢复成原多索引格式
df_final = df_resampled_wide.stack(level='id').reset_index().set_index(['date', 'id'])

方法二:GroupBy自定义函数(更直观)

通过自定义函数,让每个id的组都对齐全局的BM日期序列:

# 先定义全局BM时间序列(同方法一)
start_bm = df.index.get_level_values('date').min().to_period('BM').start_time
end_bm = pd.to_datetime('2024-12-31').to_period('BM').start_time
full_bm_dates = pd.date_range(start=start_bm, end=end_bm, freq='BM')

# 自定义重采样函数:让每个组对齐全局日期
def resample_to_full_range(group):
    return group.reindex(full_bm_dates).asfreq('BM')

# 应用到每个id的组
df_final = df.groupby('id', group_keys=False).apply(resample_to_full_range)

关键说明

  • 如果你不需要从数据集最早日期开始,也可以直接手动指定start_bm(比如pd.to_datetime('2014-01-31'))
  • asfreq('BM')会保留BM频率的索引,同时将原数据中没有的日期填充为NaN,符合你的需求

内容的提问来源于stack exchange,提问作者senorita.xi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 02:13:22