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

如何用Pandas实现DataFrame按里程区间关联并分组聚合?

刚好做过类似的里程区间匹配+聚合场景,用Pandas完全可以实现这种SQL风格的关联分组逻辑,我给你一步步拆解:

1. 先模拟示例数据(方便你对照测试)

先造两个符合你描述的DataFrame,实际使用时替换成你的真实数据即可:

import pandas as pd
import numpy as np

# DataFrame1:5米间隔的里程区间数据
df_section = pd.DataFrame({
    'Section': ['A', 'A', 'B', 'B'],
    'chainage_from': [0, 5, 0, 5],
    'chainage_to': [5, 10, 5, 10],
    'Frame': ['F1', 'F2', 'F3', 'F4']
})

# DataFrame2:1米间隔的测点数据
df_points = pd.DataFrame({
    'Section': ['A']*10 + ['B']*10,
    'Chainage': list(range(0,10)) + list(range(0,10)),
    'Col1': np.random.randint(1,10,20),
    'Col2': np.random.randint(1,20,20),
    'Col3': np.random.rand(20),
    'Col4': np.random.rand(20),
    'Col5': np.random.rand(20),
    'Col6': np.random.rand(20),
    'Col7': np.random.rand(20),
    'Col8': np.random.rand(20)
})

2. 核心:按Section关联+里程区间匹配

这里推荐用pd.merge_asof,它专门处理有序键的区间匹配,比循环/apply高效N倍,尤其适合大数据量。不过要先满足两个前提:

  • 两个DataFrame都要按Section和里程列排序
  • 确保区间是连续不重叠的(你的数据是5米间隔,应该没问题)

代码实现:

# 先对两个表按Section+里程列排序(merge_asof要求右侧表的匹配键是有序的)
df_section_sorted = df_section.sort_values(['Section', 'chainage_from'])
df_points_sorted = df_points.sort_values(['Section', 'Chainage'])

# 执行区间匹配:同Section下,把测点的Chainage匹配到对应的里程区间
merged = pd.merge_asof(
    df_points_sorted,
    df_section_sorted,
    left_on='Chainage',
    right_on='chainage_from',
    by='Section',  # 按Section分组匹配,避免跨Section错误匹配
    direction='backward'  # 找到<=当前Chainage的最大chainage_from,也就是对应的区间
)

# 过滤掉Chainage超出区间上限的行(防止极端情况的错误匹配)
merged = merged[merged['Chainage'] < merged['chainage_to']]

如果你的数据量极小,也可以用简单的apply方式(但效率低,不推荐大数据):

def map_to_frame(row):
    # 找到同Section下符合里程区间的Frame
    match = df_section[
        (df_section['Section'] == row['Section']) &
        (df_section['chainage_from'] <= row['Chainage']) &
        (df_section['chainage_to'] > row['Chainage'])
    ]
    return match['Frame'].iloc[0] if not match.empty else None

df_points['Frame'] = df_points.apply(map_to_frame, axis=1)
merged = df_points.dropna(subset=['Frame'])

3. 按Frame分组聚合

最后一步就是按Frame分组,给不同列指定对应的聚合规则,和SQL的GROUP BY+聚合函数完全对应:

# 定义聚合规则字典:键是列名,值是对应的聚合方法
aggregation_rules = {
    'Col1': 'sum',    # 列1求和
    'Col2': 'max',    # 列2取最大值
    'Col3': 'mean',   # 列3求平均
    'Col4': 'mean',
    'Col5': 'mean',
    'Col6': 'mean',
    'Col7': 'mean',
    'Col8': 'mean'
}

# 分组聚合,最后用reset_index把Frame从索引变回列
final_result = merged.groupby('Frame').agg(aggregation_rules).reset_index()

这样得到的final_result就是你要的目标输出啦!

几个关键注意事项

  • 确保里程列(chainage_from/chainage_to/Chainage)的数据类型一致,比如都是int或float,避免匹配错误
  • 如果你的Section是多维度分组(比如加个Line列),可以把by参数改成列表:by=['Line', 'Section']
  • 提前检查df_section的区间,确保每个Section下的区间是连续且不重叠的,否则会出现匹配混乱

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:07:23