Pandas:如何基于另一个DataFrame的索引重采样行数据
按自定义时间索引对Demand重采样求和的最优方案
先把你的原始数据和目标索引整理成可运行的pandas代码,方便后续操作:
import pandas as pd # 原始需求中的DataFrame df = pd.DataFrame({ 'zone': [48]*5, 'Datetime': pd.to_datetime([ '2020-08-02 00:00:00', '2020-08-02 01:00:00', '2020-08-02 02:00:00', '2020-08-02 03:00:00', '2020-08-02 04:00:00' ]), 'Demand': [14292.55, 14243.49, 9130.84, 10483.51, 10014.97] }) # 需要用来重采样的目标时间索引 target_index = pd.to_datetime([ '2020-08-02 03:00:00', '2020-08-02 06:00:00', '2020-08-02 07:00:00', '2020-08-02 10:00:00' ])
你的核心需求应该是:把原始数据里的Demand值,按照target_index划分的时间区间做求和聚合,最终结果对齐到这个目标索引上对吧?这里有两种高效且易维护的方案,都是利用pandas内置功能实现的,算是最优解了:
方案一:区间分组法(直观清晰)
这种方法适合需要明确看到时间区间范围的场景:
- 补全区间边界:因为
target_index只给了分界点,我们需要把原始数据的最早时间加进去,确保所有数据都被覆盖:
# 合并原始最早时间和目标索引,排序后作为区间边界 bins = pd.concat([pd.Series(df['Datetime'].min()), pd.Series(target_index)]).sort_values()
- 映射区间并求和:用
pd.cut把每个时间点分到对应的区间,再分组求和:
# 给每条数据打上所属的时间区间标签 df['time_interval'] = pd.cut(df['Datetime'], bins=bins, include_lowest=True) # 按区域和区间分组求和,最后把区间右端点设为索引(对齐目标索引) result = df.groupby(['zone', 'time_interval'])['Demand'].sum().reset_index() result['interval_end'] = result['time_interval'].apply(lambda x: x.right) result = result.set_index('interval_end').drop('time_interval', axis=1)
方案二:merge_asof匹配法(直接对齐目标索引)
如果你希望结果直接以target_index为索引,且每个索引对应从上一个分界点到当前点的时间段求和,这个方法更简洁:
# 把目标索引转成DataFrame,用于后续匹配 target_df = pd.DataFrame({'interval_end': target_index}).sort_values('interval_end') # 用merge_asof匹配每条数据对应的最近目标分界点(向后匹配,即找比当前时间大的最早分界点) merged = pd.merge_asof(df.sort_values('Datetime'), target_df, left_on='Datetime', right_on='interval_end', direction='backward') # 按区域和分界点分组求和,直接得到对齐目标索引的结果 result = merged.groupby(['zone', 'interval_end'])['Demand'].sum().reset_index().set_index('interval_end')
方案优势
- 完全基于pandas原生函数,效率远高于手动循环判断区间,处理大数据量时优势明显
- 代码逻辑清晰,容易理解和维护,还能轻松扩展到多区域(zone)的场景
- 对于目标索引中没有对应数据的时间段(比如你的例子里06:00之后的区间),可以用
result.reindex(target_index, fill_value=0)快速补0
内容的提问来源于stack exchange,提问作者Gal Perelman
相关产品推荐
相关产品推荐

