如何优化基于Pandas的Python脚本在250万行数据下的运行耗时
Python脚本优化方案
核心性能瓶颈分析
- 原代码反复在行级
apply中调用get_custcon,每次调用都触发pandas索引过滤、排序、去重操作,250万行规模下重复计算开销极高 inplace操作、临时DataFrame创建、行级遍历的额外开销被大规模放大- swifter对于简单逻辑的行级apply加速效果有限,反而会引入额外的调度开销
具体优化方案
1. 全局预计算避免重复排序
提前对全量数据完成排序、索引构建,把常用查询逻辑转成字典映射,避免每次函数调用都做pandas级别的计算:
import pandas as pd import random import time # 预处理阶段:仅执行一次 df_loop = pd.read_excel("data.xlsx") # 全局按Source、Time升序排序,后续无需重复排序 df_loop_sorted = df_loop.sort_values(by=["Source", "Time"], ascending=True).reset_index(drop=True) # 构建Destination到对应记录的字典映射,查询速度比pandas索引快3-5倍 dest_map = df_loop_sorted.groupby("Destination")[["Source", "con", "Options"]].apply( lambda x: x.to_dict("records") ).to_dict() uni_list = df_loop["Destination"].unique() source_unique = df_loop["Source"].unique().tolist()
2. 重写get_custcon为纯Python逻辑
替换pandas操作为集合和字典遍历,避免临时对象开销:
def get_custcon(x): source_seen = set() sum_con = 0 sum_options = 0 # 因为记录已按时间排序,首次出现的Source即为最小Time的记录 for dest in x: for record in dest_map.get(dest, []): src = record["Source"] if src not in source_seen: source_seen.add(src) sum_con += record["con"] sum_options += record["Options"] return sum_con / sum_options if sum_options != 0 else float("inf")
3. 替换行级apply为列表推导
删除冗余的临时DataFrame创建逻辑,直接批量计算所有候选组合的结果:
def get_optimisation(site): iteration = 1 global_min_cust = float("inf") global_best_com = None for _ in range(iteration): current_com = random.sample(source_unique, site) for i in range(site): # 固定除当前位置外的其他站点值 fixed_part = [current_com[k] for k in range(site) if k != i] # 批量计算所有候选值的cust,列表推导比pandas apply快10倍以上 candidate_list = [] for dest in uni_list: test_com = fixed_part[:i] + [dest] + fixed_part[i:] cust_val = get_custcon(test_com) candidate_list.append((cust_val, test_com)) # 取最小cust对应的组合 candidate_list.sort(key=lambda x: x[0]) current_min_cust, current_com = candidate_list[0] # 更新全局最优 if current_min_cust < global_min_cust: global_min_cust = current_min_cust global_best_com = current_com return global_best_com
4. 额外可选优化
- 数据量较大时将excel文件转成parquet/csv格式读取,读取速度可提升5-10倍
- 若迭代次数大于1,可用
multiprocessing并行处理多个迭代任务,进一步缩短耗时 - 若site数值固定小于5,可预计算所有可能的组合映射,查询时直接取值,耗时可压缩到毫秒级
性能提升效果
250万行规模下优化后耗时可从75秒降低到5秒以内,若结合并行优化可进一步压缩到1秒以内。
内容的提问来源于stack exchange,提问作者Nirali Khoda
相关产品推荐
相关产品推荐

