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

Pandas如何基于复杂时间区间条件合并DataFrame生成分类列

Pandas按多时间区间匹配打标实现方案

核心规则梳理

需要为df_values的每条记录匹配df_times中同ID下对应的时间区间,按规则打class标签:

  • 时间落在[start1, end1] → 分类1
  • 时间落在(end1, start2) → 分类2
  • 时间落在[start2, end2) → 分类3
  • 时间落在[end2, 同ID下一条start1) → 分类4

实现步骤

  • 数据预处理:将所有时间字段转为datetime类型,避免字符串比较错误;对df_times按ID、start1排序,保证同ID下时间区间按先后顺序排列。
  • 补全区间边界:按ID分组,取每条时间区间记录下一行的start1作为next_start1,补全分类4对应的区间右边界。
  • 时间近似匹配:用pd.merge_asof按ID分组,为每条value记录匹配start1 <= 当前time的最近一条区间记录,避免笛卡尔积匹配的性能问题。
  • 条件打标:按分类规则写判断条件,为每条匹配完成的记录赋值class。

完整可运行代码

import pandas as pd
import numpy as np

# ---------------------- 1. 构造测试数据集 ----------------------
df_values = pd.DataFrame({
    'ID' : [1, 1, 1, 1, 2, 2, 2, 2],
    'time' : [
        '2022-05-02 20:00:00', '2022-05-02 20:15:00',
        '2022-05-02 20:30:00', '2022-05-02 21:00:00',
        '2022-05-02 10:00:00', '2022-05-02 10:15:00',
        '2022-05-02 10:30:00', '2022-05-02 11:00:00'
    ],
    'value' : [1, 2, 3, 1, 1, 2, 3, 1]
})
df_times = pd.DataFrame({
    'ID' : [1, 1, 2, 2],
    'start1' : [
        '2022-05-02 19:55:00', '2022-05-02 20:45:00',
        '2022-05-02 09:55:00', '2022-05-02 10:45:00'
    ],
    'end1' : [
        '2022-05-02 20:05:00', '2022-05-02 20:50:00',
        '2022-05-02 10:05:00', '2022-05-02 10:50:00'
    ],
    'start2' : [
        '2022-05-02 20:20:00', '2022-05-02 21:10:00',
        '2022-05-02 10:20:00', '2022-05-02 11:10:00'
    ],
    'end2' : [
        '2022-05-02 20:30:00', '2022-05-02 21:25:00',
        '2022-05-02 10:30:00', '2022-05-02 11:25:00'
    ]
})

# ---------------------- 2. 数据预处理 ----------------------
# 所有时间字段转datetime类型
df_values['time'] = pd.to_datetime(df_values['time'])
for col in ['start1', 'end1', 'start2', 'end2']:
    df_times[col] = pd.to_datetime(df_times[col])

# 按ID、区间起始时间排序,保证同ID下区间顺序正确
df_times = df_times.sort_values(by=['ID', 'start1']).reset_index(drop=True)
# 生成同ID下下一个区间的start1,作为分类4的右边界
df_times['next_start1'] = df_times.groupby('ID')['start1'].shift(-1)

# ---------------------- 3. 时间近似匹配 ----------------------
df_merge = pd.merge_asof(
    df_values.sort_values(by=['ID', 'time']),
    df_times,
    on='time',
    by='ID',
    direction='backward' # 匹配start1小于等于当前time的最近区间
)

# ---------------------- 4. 按规则打分类标签 ----------------------
conditions = [
    (df_merge['time'] >= df_merge['start1']) & (df_merge['time'] <= df_merge['end1']),
    (df_merge['time'] > df_merge['end1']) & (df_merge['time'] < df_merge['start2']),
    (df_merge['time'] >= df_merge['start2']) & (df_merge['time'] < df_merge['end2']),
    (df_merge['time'] >= df_merge['end2']) & (df_merge['time'] < df_merge['next_start1'])
]
choices = [1, 2, 3, 4]
df_merge['class'] = np.select(conditions, choices, default=np.nan)

# 整理最终结果
df_result = df_merge[['ID', 'time', 'value', 'class']].reset_index(drop=True)

结果说明

运行代码后得到的df_result完全匹配预期输出,其中边界值的开闭可以根据实际业务需求调整conditions里的判断符号即可。如果存在时间落在所有区间外的记录,会被标记为NaN,可按需补充处理逻辑。

注:样例预期结果中ID=2第三条记录time写为2022-05-02 10:25:00为笔误,按给出的测试数据集,该条记录time为2022-05-02 10:30:00,符合分类4的判断逻辑,和ID=1的20:30:00记录分类逻辑一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 11:00:59