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

如何判断Pandas主DataFrame的日期是否落在另一DataFrame的日期范围内

多日期范围匹配解决方案

需求说明

现有两个Pandas DataFrame:

  • main_df:约20万条事件数据,包含事件编号、时间戳及其他字段
  • df_ranges:包含多个不重叠的日期范围,每个范围对应唯一名称

需要为main_df新增一列in_range,标记每条记录的时间属于哪个范围,不属于任何范围则为None。

数据示例

main_df

event_nrdatedetail_1detail_2
e_00012010-01-02 07:30:001100
e_00022010-06-05 07:30:000132

df_ranges

startendname
2010-02-252010-03-06range_1
2010-06-022010-06-08range_2

期望结果

event_nrdatedetail_1detail_2in_range
e_00012010-01-02 07:30:001100None
e_00022010-06-05 07:30:000132range_2

高效实现方案(适合20万条数据)

由于数据量较大,推荐使用pd.merge_asof,这是专门针对有序键的高效合并方法,适合处理范围匹配场景:

步骤1:统一日期类型

先确保所有日期列都是datetime类型:

import pandas as pd

# 转换main_df的date列
main_df['date'] = pd.to_datetime(main_df['date'])
# 转换df_ranges的start和end列
df_ranges['start'] = pd.to_datetime(df_ranges['start'])
df_ranges['end'] = pd.to_datetime(df_ranges['end'])

步骤2:排序范围数据

merge_asof要求右侧DataFrame按合并键排序,这里按start排序:

df_ranges_sorted = df_ranges.sort_values('start')

步骤3:执行范围匹配

使用merge_asof匹配,同时过滤掉超出end范围的记录:

# 先按date和start做向后合并
merged = pd.merge_asof(
    main_df.sort_values('date'),
    df_ranges_sorted,
    left_on='date',
    right_on='start',
    direction='backward'
)

# 过滤掉date大于end的记录,将对应的name设为None
merged['in_range'] = merged.apply(
    lambda x: x['name'] if x['date'] <= x['end'] else None,
    axis=1
)

# 保留原main_df的列顺序,去掉合并时新增的start/end列
result = merged[['event_nr', 'date', 'detail_1', 'detail_2', 'in_range']]

备选方案(小数据量适用)

如果数据量较小,可以用apply遍历每条记录,但效率较低,不适合20万条数据:

def get_range_name(date):
    for _, row in df_ranges.iterrows():
        if row['start'] <= date <= row['end']:
            return row['name']
    return None

main_df['in_range'] = main_df['date'].apply(get_range_name)

内容的提问来源于stack exchange,提问作者Con-cat-enate

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 01:55:37