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

基于另一数据框的类别与范围填充Pandas列

按轨道类别+位置区间匹配添加Speed列的解决方案

以下提供两种实用的实现方法,先给出示例数据方便你对应自己的场景调整:

import pandas as pd

# 示例DF1:待补充Speed的主表
DF1 = pd.DataFrame({
    'TrackType': ['A', 'A', 'B', 'B'],
    'LocationFrom': [10, 30, 5, 25],
    'LocationTo': [20, 40, 15, 35]
})

# 示例DF2:包含轨道类别、位置区间、对应限速的参考表
DF2 = pd.DataFrame({
    'TrackType': ['A', 'A', 'B', 'B'],
    'StartLoc': [0, 25, 0, 20],
    'EndLoc': [25, 50, 20, 40],
    'Speed': [60, 80, 50, 70]
})

方法一:分组后使用merge_asof

利用merge_asof的范围匹配能力,先按轨道类别分组,再在组内完成区间匹配,确保类别优先匹配:

# 先对参考表按轨道类别+起始位置排序(merge_asof要求右表按匹配键排序)
DF2_sorted = DF2.sort_values(['TrackType', 'StartLoc'])

# 定义分组处理逻辑
def match_speed_by_group(group):
    track_type = group.name
    # 筛选当前轨道类别的参考数据
    df2_sub = DF2_sorted[DF2_sorted['TrackType'] == track_type]
    # 对当前组的起始位置排序(merge_asof要求左表按匹配键排序)
    group_sorted = group.sort_values('LocationFrom')
    # 执行merge_asof匹配,按轨道类别关联,按LocationFrom匹配StartLoc的最近区间
    merged = pd.merge_asof(
        group_sorted,
        df2_sub,
        left_on='LocationFrom',
        right_on='StartLoc',
        direction='backward',  # 取小于等于LocationFrom的最大StartLoc对应的区间
        by='TrackType'         # 强制先按轨道类别分组匹配
    )
    # 额外校验:确保LocationFrom落在参考区间内(避免匹配到不相关的区间)
    merged = merged[merged['LocationFrom'] <= merged['EndLoc']]
    # 恢复原表的索引顺序
    return merged.sort_index()

# 按轨道类别分组处理,合并结果
result = DF1.groupby('TrackType', group_keys=False).apply(match_speed_by_group)
# 整理输出列
result = result[['TrackType', 'LocationFrom', 'LocationTo', 'Speed']]

方法二:IntervalIndex + 分组映射

为每个轨道类别构建位置区间索引,直接匹配主表的位置值:

# 为每个轨道类别创建区间-限速的映射字典
speed_interval_maps = {}
for track_type, df2_group in DF2.groupby('TrackType'):
    # 创建全闭区间(可根据实际需求调整为'left'/'right'/'neither')
    intervals = pd.IntervalIndex.from_arrays(df2_group['StartLoc'], df2_group['EndLoc'], closed='both')
    speed_interval_maps[track_type] = pd.Series(df2_group['Speed'].values, index=intervals)

# 定义单行匹配函数
def get_matched_speed(row):
    speed_series = speed_interval_maps[row['TrackType']]
    # 查找LocationFrom所在的区间对应的限速
    match_idx = speed_series.index.get_indexer([row['LocationFrom']])[0]
    # 若未匹配到返回None(可根据需求改为默认值)
    return speed_series.iloc[match_idx] if match_idx != -1 else None

# 为DF1添加Speed列
DF1['Speed'] = DF1.apply(get_matched_speed, axis=1)

注意事项

  • 若需要同时校验LocationFrom和LocationTo都落在DF2的区间内,可在代码中添加额外判断(比如merged = merged[(merged['LocationFrom'] >= merged['StartLoc']) & (merged['LocationTo'] <= merged['EndLoc'])])
  • merge_asof的direction参数可根据需求调整:backward取最近的左区间,forward取最近的右区间,nearest取最近的任意区间
  • IntervalIndex的closed参数要和你的区间定义一致,避免匹配错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 05:24:31