Python多DataFrame匹配:查找事件所属时间窗口索引
匹配事件到对应的时间窗口解决方案
嘿,我来帮你搞定这个把事件映射到对应时间窗口的问题!你的需求很明确:把df_timestamps里的每个事件时间戳,匹配到df_features中包含它的窗口索引。先帮你分析下之前代码的问题,再给出两种可行的解决方案。
先排查你之前代码的问题
你之前写的mask = df_features['Start'][0]< df_k[0][0] & df_features['End']>df_k[0][128]有几个明显的问题:
- 逻辑运算符优先级错误:
&的优先级比比较运算符高,所以会先计算df_k[0][0] & df_features['End'],这完全不是你想要的逻辑,必须给每个比较表达式加上括号,比如(df_features['Start'][0] < 时间戳) & (df_features['End'][0] > 时间戳)。 - 只匹配了第一个窗口:你用
[0]只取了df_features的第一行数据,这样只能检查第一个窗口,没法遍历所有窗口找符合条件的。 - 时间格式未转换:如果你的
Start、End和timestamp是字符串类型,直接比较会按字典序而非时间顺序,必须先转换成datetime类型才能正确比较。
解决方案步骤
第一步:统一时间格式
首先把所有时间列转换成pandas的datetime类型,这是正确比较时间的前提:
import pandas as pd # 先构造你的示例数据(方便测试) df_features = pd.DataFrame({ '索引': [1], 'feature1': [20], 'feature2': [1.5], 'feature3': [3], 'feature4': [1], 'Start': ['2020/04/05 11:05:15'], 'End': ['2020/04/05 11:05:35'] }).set_index('索引') df_timestamps = pd.DataFrame({ '索引': [1], 'event': ['start rest'], 'timestamp': ['2020-04-05 11:05:25'] }) # 转换时间列为datetime类型 df_features['Start'] = pd.to_datetime(df_features['Start'], format='%Y/%m/%d %H:%M:%S') df_features['End'] = pd.to_datetime(df_features['End'], format='%Y/%m/%d %H:%M:%S') df_timestamps['timestamp'] = pd.to_datetime(df_timestamps['timestamp'], format='%Y-%m-%d %H:%M:%S')
方法一:遍历事件匹配窗口(适合小数据集)
如果你的数据量不大,直接遍历每个事件的时间戳,筛选出包含它的窗口即可:
# 定义一个函数,输入时间戳,返回对应的窗口索引 def get_window_idx(timestamp): # 筛选满足「Start ≤ timestamp ≤ End」的窗口 match_mask = (df_features['Start'] <= timestamp) & (df_features['End'] >= timestamp) # 如果有匹配的窗口,返回第一个匹配的索引;没有则返回None return df_features[match_mask].index[0] if match_mask.any() else None # 给df_timestamps添加「窗口索引」列 df_timestamps['窗口索引'] = df_timestamps['timestamp'].apply(get_window_idx) # 查看结果 print(df_timestamps)
运行后你会看到示例中的start rest事件对应的窗口索引是1,完全符合预期。
方法二:用merge_asof高效匹配(适合大数据集)
如果你的数据集很大,遍历的效率会很低,推荐用pandas的merge_asof方法,这是专门为时间序列匹配设计的高效工具:
# 先把df_features的索引恢复成列,方便后续合并 df_features_flat = df_features.reset_index()[['索引', 'Start', 'End']].sort_values('Start') # 对df_timestamps按时间戳排序(merge_asof要求输入已排序) df_timestamps_sorted = df_timestamps.sort_values('timestamp') # 用merge_asof匹配最近的窗口起始时间 merged = pd.merge_asof( df_timestamps_sorted, df_features_flat, left_on='timestamp', right_on='Start', direction='backward' # 找小于等于当前时间戳的最大窗口起始时间 ) # 过滤掉时间戳超出窗口结束时间的情况(确保事件真的在窗口内) merged = merged[merged['timestamp'] <= merged['End']] # 合并回原数据,恢复原顺序(如果需要) final_result = merged.merge(df_timestamps, on=['索引', 'event', 'timestamp'], how='right') # 查看最终结果 print(final_result[['索引', 'event', 'timestamp', '窗口索引']])
这个方法的效率比遍历高很多,适合处理十万级以上的数据集。
内容的提问来源于stack exchange,提问作者Dwayne Dillen
相关产品推荐
相关产品推荐

