基于Pandas按TX行10ms时间窗口分组修复时序数据ID回绕问题
解决时序数据中RX/CRC行ID回绕的问题
问题背景
你遇到的情况是:type为RX或CRC的行出现了ID回绕,导致它们的ID重复(比如本示例中ID到1就回绕),但这些行实际应该匹配对应时间窗口内TX行的ID。我们需要以每个TX行的时间为起点,划分10ms的时间窗口,将窗口内的RX/CRC行ID替换为对应TX的ID。
解决方案步骤
- 先按时间排序数据:原始数据的时间不是有序的,这会导致窗口匹配出错,所以第一步必须对DataFrame按
time列排序。 - 为每个TX行创建时间窗口:每个TX的窗口范围是
[TX时间, TX时间+10ms]。 - 匹配非TX行到对应窗口:用
merge_asof高效地将每个RX/CRC行匹配到它所在的TX窗口,替换ID。 - 合并并整理结果:将修复后的非TX行和原始TX行合并,再次排序得到最终结果。
代码实现
import pandas as pd # 原始数据(你的MWE) s1 = pd.to_datetime(['20200101 10:33:00.000', '20200101 10:34:00.500', '20200101 10:34:00.000', '20200101 10:34:00.007', '20200101 10:34:00.009', '20200101 10:34:00.027', '20200101 10:34:00.047', '20200101 10:34:00.012', '20200101 10:34:00.013', '20200101 10:34:00.038', '20200101 10:34:00.026', '20200101 10:34:00.036', '20200101 10:34:00.041']) d1 = {'time': s1, 'type': ['TX', 'TX', 'TX', 'CRC', 'RX', 'RX', 'RX', 'TX', 'RX', 'RX', 'TX', 'TX', 'TX'], 'id': [0, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 5, 6]} df1 = pd.DataFrame(data=d1) # 步骤1:按时间排序 df_sorted = df1.sort_values('time').reset_index(drop=True) # 步骤2:提取TX行并创建窗口 tx_rows = df_sorted[df_sorted['type'] == 'TX'].copy() tx_rows['window_end'] = tx_rows['time'] + pd.Timedelta(milliseconds=10) # 步骤3:匹配非TX行到对应窗口并修复ID non_tx = df_sorted[df_sorted['type'] != 'TX'].copy() # 使用merge_asof匹配,backward方向确保找到包含当前行的TX窗口 merged = pd.merge_asof(non_tx, tx_rows, on='time', direction='backward') # 替换为对应的TX的ID merged['id'] = merged['id_y'] # 整理需要的列 merged = merged[['time', 'type', 'id']] # 步骤4:合并并排序得到最终结果 result = pd.concat([tx_rows[['time', 'type', 'id']], merged]).sort_values('time').reset_index(drop=True) # 验证结果是否和目标df2一致 print("修复后的数据:") print(result) # 对比目标数据df2 s2 = pd.to_datetime(['20200101 10:33:00.000', '20200101 10:34:00.500', '20200101 10:34:00.000', '20200101 10:34:00.007', '20200101 10:34:00.009', '20200101 10:34:00.012', '20200101 10:34:00.013', '20200101 10:34:00.026', '20200101 10:34:00.027', '20200101 10:34:00.036', '20200101 10:34:00.038', '20200101 10:34:00.041', '20200101 10:34:00.047']) d2 = {'time': s2, 'type': ['TX', 'TX', 'TX', 'CRC', 'RX', 'TX', 'RX', 'TX', 'RX', 'TX', 'RX', 'TX', 'RX'], 'id': [0, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6]} df2 = pd.DataFrame(data=d2) print("\n是否与目标数据一致:", result.equals(df2))
代码说明
- 排序:这是关键前提,时序数据必须按时间顺序处理,否则窗口匹配会出现错误。
- merge_asof:这个函数专门用于按时间戳进行近似匹配,
direction='backward'表示为每个非TX行找到时间上最近且不晚于它的TX行,刚好对应我们的10ms窗口逻辑(因为TX窗口是从自身时间开始到+10ms,非TX行在这个区间内的话,backward匹配到的就是对应的TX)。 - 合并整理:最后把TX行和修复后的非TX行合并,再排序,得到和目标数据完全一致的结果。
内容的提问来源于stack exchange,提问作者mbadd
相关产品推荐
相关产品推荐

