Pandas重采样:借助高分辨率时序B将A上采样至15分钟并缩放
解决基于权重的时序上采样问题
这种用另一个时序数据作为权重来完成上采样的需求,确实没法直接用resample搞定——因为resample的插值逻辑是基于时间的,而我们需要的是基于外部变量的比例分配。不过用Pandas的merge_asof + 分组计算就能轻松实现,我给你一步步拆解:
第一步:把原始数据转成规范的Pandas时序格式
首先得把你给的字符串数据转换成带DatetimeIndex的DataFrame,这样才能方便后续的时间匹配:
import pandas as pd # 构造A的时序数据 a_raw = [ ("2017-11-01 07:30:00", 77.0), ("2017-11-01 08:00:00", 214.0), ("2017-11-01 08:30:00", 470.0), ("2017-11-01 09:00:00", 714.0) ] df_a = pd.DataFrame(a_raw, columns=["timestamp", "irrad"]).set_index("timestamp") df_a.index = pd.to_datetime(df_a.index) # 构造B的时序数据 b_raw = [ ("2017-11-01 07:15:00", 12.67), ("2017-11-01 07:30:00", 29.70), ("2017-11-01 07:45:00", 46.80), ("2017-11-01 08:00:00", 74.07), ("2017-11-01 08:15:00", 166.27), ("2017-11-01 08:30:00", 256.50), ("2017-11-01 08:45:00", 271.70), ("2017-11-01 09:00:00", 354.33) ] df_b = pd.DataFrame(b_raw, columns=["timestamp", "util"]).set_index("timestamp") df_b.index = pd.to_datetime(df_b.index)
第二步:匹配每个B的时间点到对应的A值
我们需要把B的每个15分钟点,关联到它所属的30分钟区间对应的A值。这里用merge_asof来实现向后匹配——也就是给每个B的时间点找最近的、不晚于它的A的时间点:
# 重置索引以便merge,匹配后每个B的util都会带上对应的A的irrad值 merged = pd.merge_asof( df_b.reset_index(), df_a.reset_index(), left_on="timestamp", right_on="timestamp", direction="backward" )
第三步:按A值分组计算权重和最终结果
接下来,对每个A的irrad值对应的两个B的点,计算每个B值在该组中的占比(权重),再用A值乘以权重得到final值:
# 计算每个irrad组内的util总和 merged["group_util_sum"] = merged.groupby("irrad")["util"].transform("sum") # 计算权重:当前util / 组内总和 merged["weight"] = merged["util"] / merged["group_util_sum"] # 计算final值,保留1位小数和例子对齐 merged["final"] = (merged["irrad"] * merged["weight"]).round(1)
第四步:整理成目标格式
最后筛选出你需要的时间区间,得到最终结果:
# 筛选7:30到8:30的结果,和你的示例一致 df_final = merged[["timestamp", "final"]].set_index("timestamp") df_final = df_final.loc["2017-11-01 07:30":"2017-11-01 08:30"]
运行后得到的结果和你给出的B['final']完全一致:
final timestamp 2017-11-01 07:30:00 54.0 2017-11-01 07:45:00 82.9 2017-11-01 08:00:00 131.1 2017-11-01 08:15:00 184.8 2017-11-01 08:30:00 285.2
为什么这个方法可行?
核心思路是:
- 用
merge_asof完成时间维度的关联,把A的30分钟值"映射"到对应的两个B的15分钟点上; - 用分组计算实现基于B值的权重分配,而不是简单的时间插值。
如果你的数据有更复杂的时间对齐情况,只需要调整merge_asof的direction参数或者添加tolerance来控制匹配范围就行。
内容的提问来源于stack exchange,提问作者ardms
相关产品推荐
相关产品推荐

