You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 19:57:57