You need to enable JavaScript to run this app. 如何优化基于Pandas的Python脚本在250万行数据下的运行耗时
优惠活动
大模型
产品
解决方案
定价
更多

如何优化基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 15:24:03