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

如何用Pandas语法实现DataFrame按时间戳匹配日期范围的关联查询?

Pandas实现时间范围关联(替代SQL的范围JOIN)

你需要的是将带时间戳的DataFrame与包含日期范围的DataFrame做关联,对应SQL中的笛卡尔积加时间过滤逻辑,以下是几种纯Pandas的实现方式:

先明确SQL逻辑对应的需求

你的SQL查询本质是取两个表的笛卡尔积,然后筛选出df1.timestamp落在df2.FromDate和df2.ToDate之间的所有组合,返回双方的所有列。

select df1.*, df2.*
from df1, df2
where df1.timestamp >= df2.fromdate
and df1.timestamp <= df2.todate

方法一:交叉合并后过滤(小数据集首选)

Pandas 1.2.0及以上支持how='cross'实现笛卡尔积,之后直接用布尔索引过滤时间条件,逻辑最直观。

import pandas as pd

# 构造示例数据
df1 = pd.DataFrame({
    'timestamp': pd.to_datetime(['2023-01-05', '2023-02-10', '2023-03-15']),
    'value1': [10, 20, 30]
})

df2 = pd.DataFrame({
    'FromDate': pd.to_datetime(['2023-01-01', '2023-02-01', '2023-03-01']),
    'ToDate': pd.to_datetime(['2023-01-31', '2023-02-28', '2023-03-31']),
    'metadata': ['A', 'B', 'C']
})

# 执行交叉合并+过滤
result = df1.merge(df2, how='cross')
result = result[(result['timestamp'] >= result['FromDate']) & (result['timestamp'] <= result['ToDate'])]

优缺点:代码简单易读,但如果两个DataFrame数据量大,笛卡尔积会占用大量内存,仅适合小数据集。

方法二:逐行匹配关联(中等数据量适用)

通过apply遍历df1的每一行,找到df2中符合时间范围的记录并合并,避免全量笛卡尔积,内存占用更低。

def match_metadata(row):
    # 筛选当前timestamp对应的df2行
    mask = (df2['FromDate'] <= row['timestamp']) & (df2['ToDate'] >= row['timestamp'])
    matched_rows = df2[mask].copy()
    # 把当前df1的列值补充到匹配结果中
    matched_rows['timestamp'] = row['timestamp']
    matched_rows['value1'] = row['value1']
    return matched_rows

# 合并所有匹配结果
result = pd.concat([match_metadata(row) for _, row in df1.iterrows()], ignore_index=True)
# 调整列顺序,和SQL输出对齐
result = result[['timestamp', 'value1', 'FromDate', 'ToDate', 'metadata']]

优缺点:内存占用比方法一低,但iterrows()遍历速度较慢,适合中等规模数据。

方法三:区间索引匹配(大数据量高效方案)

利用Pandas的IntervalIndex将df2的日期范围转为区间,通过索引快速匹配timestamp对应的区间,效率最高。

# 为df2创建包含日期范围的IntervalIndex(closed='both'表示包含区间两端)
df2['date_interval'] = pd.IntervalIndex.from_arrays(df2['FromDate'], df2['ToDate'], closed='both')

# 为df1的每个timestamp找到对应的df2行索引
def get_interval_idx(timestamp):
    try:
        return df2['date_interval'].get_loc(timestamp)
    except KeyError:
        return -1  # 无匹配时返回-1

df1['interval_idx'] = df1['timestamp'].apply(get_interval_idx)

# 过滤无匹配的行,然后关联df2
result = df1[df1['interval_idx'] != -1].merge(df2, left_on='interval_idx', right_index=True)
# 清理多余列并调整顺序
result = result.drop(['interval_idx', 'date_interval'], axis=1)[['timestamp', 'value1', 'FromDate', 'ToDate', 'metadata']]

优缺点:匹配效率极高,内存占用小,适合大数据量场景;需要处理无匹配的边界情况,逻辑稍复杂。

通用注意事项

  • 务必确保所有日期列都是datetime类型,可通过pd.to_datetime()统一转换,否则时间比较会出错。
  • 如果一个timestamp同时匹配多个日期范围,三种方法都会返回所有匹配组合,和SQL逻辑完全一致。

内容的提问来源于stack exchange,提问作者Joanna Boone

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:18:23