Pandas如何将月度多重索引时间序列重采样为小时粒度
Pandas 月度双层索引数据展开为逐小时填充数据实现方案
核心思路
将月度粒度的双层索引数据展开为对应月份内每小时粒度的数据,所有小时点复用所属月份的原数值,可根据数据场景选择对应实现方式:
- 若月度区间是连续无重叠的自然月(月初到月末),可直接用
resample配合前向填充实现,代码更简洁 - 若存在非连续区间、自定义起止日期的月度数据,建议按区间逐段生成逐小时索引再拼接,避免跨区间填充错误
完整实现代码
1. 原测试数据构造(补全缺失的numpy导入)
import pandas as pd import numpy as np multi_index = pd.MultiIndex.from_tuples([("2022-03-01", "2022-03-31"), ("2022-04-01", "2022-04-30"), ("2022-05-01", "2022-05-31"), ("2022-06-01", "2022-06-30")]) multi_index.names = ['month_begin', 'month_end'] df = pd.DataFrame(np.random.rand(4,100), index=multi_index)
2. 简洁实现(连续自然月场景,基于resample)
# 提取月初日期作为单层datetime索引 df_res = df.set_index(pd.to_datetime(df.index.get_level_values('month_begin'))) # 按小时粒度重采样,前向填充数值 df_res = df_res.resample('H').ffill() # 截断最后一个月月末23点之后的多余行(resample会自动生成下一个月月初的冗余行) last_end = pd.to_datetime(df.index.get_level_values('month_end').max()) + pd.Timedelta(hours=23) df_res = df_res[df_res.index <= last_end]
3. 严谨实现(自定义区间通用场景)
该方法严格按照每行指定的month_begin和month_end生成时间范围,不会出现跨区间填充错误,适配所有时间区间场景:
hourly_chunk_list = [] for (month_start, month_end), month_vals in df.iterrows(): # 生成当前区间内从首日0点到末日23点的逐小时时间序列 hour_idx = pd.date_range( start=pd.to_datetime(month_start), end=pd.to_datetime(month_end) + pd.Timedelta(hours=23), freq="H" ) # 将当前月的数值复制到所有小时行 hourly_chunk_list.append( pd.DataFrame( np.tile(month_vals.values, (len(hour_idx), 1)), index=hour_idx, columns=df.columns ) ) # 拼接所有区间的逐小时数据 df_res = pd.concat(hourly_chunk_list)
结果说明
两种方法最终输出的df_res结构完全符合预期:索引为逐小时的datetime时间点,每个时间点的100列数值和所属月份的原数值完全一致,总数据量为4个自然月的总小时数(3月744小时+4月720小时+5月744小时+6月720小时=2928行)。
注意:如果月度区间存在重叠,优先选择第二种逐段生成的方式,避免填充逻辑冲突。
内容的提问来源于stack exchange,提问作者W. Walter
相关产品推荐
相关产品推荐

