基于其他DataFrame信息高效计算距离总和(尽量不使用循环)
超1亿行DataFrame区间距离求和高效方案
核心思路
两个表体量都过亿,绝对不能使用逐行遍历、条件连接或者笛卡尔积等会引发数据膨胀的操作。核心利用df2是按车辆、月份有序存储的序列特性,通过前缀和映射+等值连接的全向量化方案实现计算,全程无遍历操作:
- 对df2按车辆分组生成月维度距离前缀和表,任意
[month_start, month_end)区间的距离总和,直接等于区间右端点的前缀和减去左端点的前缀和 - 仅通过两次等值连接就能为df1所有行匹配到对应前缀和,直接做差得到
sum_distance
实现代码
import pandas as pd # 1. 预处理df2生成前缀和映射表 # 生成和df1格式一致的年月键yyyymm df2['month_key'] = df2['Year'] * 100 + df2['Month'] # 按车辆、月份排序,计算前缀和(前缀和定义为小于当前month_key的所有月份距离之和) df2 = df2.sort_values(['vehicle', 'month_key']).reset_index(drop=True) df2['cum_distance'] = df2.groupby('vehicle')['Distance'].cumsum().shift(fill_value=0) # 提取前缀和映射表 cum_map = df2[['vehicle', 'month_key', 'cum_distance']] # 2. df1分别匹配左、右边界的前缀和 df1 = df1.merge( cum_map, how='left', left_on=['vehicle', 'month_start'], right_on=['vehicle', 'month_key'] ).rename(columns={'cum_distance': 'left_cum'}).drop('month_key', axis=1) df1 = df1.merge( cum_map, how='left', left_on=['vehicle', 'month_end'], right_on=['vehicle', 'month_key'] ).rename(columns={'cum_distance': 'right_cum'}).drop('month_key', axis=1) # 3. 计算sum_distance,空值补0(处理边界不存在的情况) df1['sum_distance'] = df1['right_cum'].fillna(0) - df1['left_cum'].fillna(0)
性能优势
- 全程为pandas原生向量化操作,比逐行
apply性能高至少1000倍,完全适配1亿行以上的数据规模 - 无数据膨胀:前缀和映射表的行数和df2一致,两次等值连接不会生成中间冗余数据
- 内存友好:可通过提前对
cum_map和df1按vehicle和month_key排序、开启分块读取等进一步优化,16G内存的普通机器也可以在分钟级完成计算
内容的提问来源于stack exchange,提问作者Unoner
相关产品推荐
相关产品推荐

