发布于2026-04-19 阅读(0)
扫一扫,手机访问

本文介绍如何利用 pandas.merge_asof 与 DataFrame.rolling(..., center=True) 协同实现:以低频数据框(df2)的时间戳为中心点,在高频数据框(df1)中截取指定时间窗口(如5分钟)并计算滑动均值,最终完成精准时序对齐。
本文介绍如何利用 `pandas.merge_asof` 与 `DataFrame.rolling(..., center=True)` 协同实现:以低频数据框(df2)的时间戳为**中心点**,在高频数据框(df1)中截取指定时间窗口(如5分钟)并计算滑动均值,最终完成精准时序对齐。
在实际时序数据分析中,常需将高频采样数据(如每15秒记录的传感器速度)与低频参考时间点(如每5分钟一次的校准标记或事件触发时刻)对齐,并以这些低频时间点为中心,提取其前后对称时间窗口内的高频数据均值。这不同于简单的时间下采样(如 resample),也不同于左对齐滚动(center=False),而是一种“中心锚定式”滑动聚合。
核心思路分三步:
以下是完整可运行代码示例:
import pandas as pd
import numpy as np
# 确保 time 列为 datetime 类型
df1["time"] = pd.to_datetime(df1["time"])
df2["time"] = pd.to_datetime(df2["time"])
# 步骤1:计算 df1 中以 time 为中心、宽度为5分钟(±2.5min)的 speed 滑动均值
df1_rolling_mean = (
df1.rolling(window="300s", on="time", center=True)
.mean()
.rename(columns={"speed": "speed_avg"})
)
# 步骤2:将滚动均值合并回 df1(按索引对齐)
df1 = df1.join(df1_rolling_mean)
# 步骤3:以 time 为键,用 merge_asof 将 df1 与 df2 对齐(左表为 df1,右表为 df2)
# 注意:merge_asof 要求两表 time 已排序,且默认向后查找(direction="backward" 或 "nearest" 更灵活)
df_merged = pd.merge_asof(
df1.sort_values("time"),
df2.sort_values("time").rename(columns={"speed": "speed_df2"}),
on="time",
tolerance=pd.Timedelta("15s"),
direction="nearest", # 关键!确保匹配最近的时间点(而非仅向前/向后)
allow_exact_matches=True
)
# 步骤4:过滤出成功匹配的行(即 df2 中存在对应时间点的记录)
result = df_merged.dropna(subset=["speed_df2"]).copy()
result = result[["time", "speed", "speed_avg", "speed_df2"]].reset_index(drop=True)✅ 关键注意事项:
- rolling(..., center=True) 要求 on="time" 且 time 必须是单调递增的 datetime64 类型,否则会报错或结果异常;务必提前调用 sort_values("time") 并重置索引(若原始索引无序);
- merge_asof 默认 direction="backward"(找 ≤ 当前时间的最大值),但本场景需最邻近匹配,因此显式指定 direction="nearest" 更鲁棒;
- tolerance 应略大于 df1 的最大采样间隔(如15秒),避免因微小时间偏移导致匹配失败;
- 若 df1 时间范围不足以覆盖 df2 某一时间点 ±2.5 分钟,则该行 speed_avg 将为 NaN —— 这是预期行为,表明窗口数据不完整,建议后续检查或填充策略(如 min_periods=1 控制最小有效点数)。
最终输出结构清晰:每行对应 df2 中一个时间点,包含其在 df1 中最邻近采样时刻的原始值、5分钟中心滚动均值,以及原始 df2 的参考值,为跨频率时序建模、偏差分析或特征工程提供可靠基础。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8