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

如何提升Pandas中pivot_table()与concat操作的执行效率?

提速你的Pandas透视表合并操作

你的代码运行缓慢的核心原因有两个:一是循环中反复调用pd.concat,每次合并都会复制整个已有DataFrame,随着数据量增大,时间复杂度会攀升至O(n²);二是多次手动切片筛选生成临时DataFrame,额外消耗了大量内存与CPU时间。下面给你几个逐步优化的方案,从易到难,速度提升效果依次增强:


方案1:先收集透视表到列表,最后一次性合并

这是改动最小的优化方案,只需调整循环逻辑,避免每次迭代都执行合并操作:

import pandas as pd
import numpy as np
from tqdm import tqdm

# 初始化空列表存储每个assignid对应的透视表结果
pivot_list = []

for assignid in tqdm(selectedTests['assignids'].unique()):
    selectedTestsForAssignID = selectedTests[selectedTests['assignids'] == assignid]
    # 直接对当前assignid下的所有memberid批量生成透视表,省去内层memberid循环
    pivot_temp = selectedTestsForAssignID.pivot_table(
        index=['memberid'],
        columns=['col1', 'col2'],
        values='col3',
        aggfunc=np.max
    )
    pivot_list.append(pivot_temp)

# 最后一次性合并所有临时透视表
selectedTestsPivotCorrect = pd.concat(pivot_list, axis=0, join='outer')

提速原因:

  • 移除了不必要的内层memberid循环——pivot_table本身支持按memberid分组处理,直接对整个selectedTestsForAssignID操作就能得到该assignid下所有memberid的结果。
  • 用列表存储临时结果,最后一次完成合并,避免了每次迭代都复制大DataFrame的开销,时间复杂度从O(n²)降到O(n)。

方案2:直接对全量数据做透视(最优解)

如果你的最终需求是每个memberid在所有assignid中,每个(col1, col2)组合下取col3的最大值,那完全不需要循环assignid,一步到位即可:

selectedTestsPivotCorrect = selectedTests.pivot_table(
    index=['memberid'],
    columns=['col1', 'col2'],
    values='col3',
    aggfunc=np.max
)

为什么这是最优解?

  • Pandas的pivot_table内部采用了高效的分组聚合算法,比手动循环快几个数量级,同时避免了所有临时DataFrame的生成,内存占用也会大幅降低。
  • 若同一个memberid在不同assignid中有重复的(col1, col2)组合,aggfunc=np.max会自动取所有记录中的最大值,和你原代码的逻辑一致(原代码concat后重复memberid会保留多条记录,若你需要去重聚合,这个方案更符合需求)。

方案3:分块分组处理(应对内存报错)

如果直接对全量数据做透视仍出现内存不足的问题,可以尝试用groupby替代手动切片,进一步优化分块处理的效率:

from tqdm import tqdm

pivot_list = []
# 按assignid分组遍历,groupby的切片比手动筛选更高效
for assignid, group in tqdm(selectedTests.groupby('assignids')):
    pivot_temp = group.pivot_table(
        index=['memberid'],
        columns=['col1', 'col2'],
        values='col3',
        aggfunc=np.max
    )
    pivot_list.append(pivot_temp)

selectedTestsPivotCorrect = pd.concat(pivot_list, axis=0, join='outer')

优势:

  • groupby会预先对数据做分组优化,比手动selectedTests[selectedTests['assignids']==assignid]的筛选速度更快,减少了重复计算。
  • 同样采用“列表收集+一次性合并”的逻辑,避免反复concat的性能损耗。

额外提速小技巧

  1. 优化数据类型:如果col1、col2是字符串或固定枚举值,可转为category类型,大幅减少内存占用并加速透视:
    selectedTests['col1'] = selectedTests['col1'].astype('category')
    selectedTests['col2'] = selectedTests['col2'].astype('category')
    
  2. 移除进度条(可选):若追求极致速度,tqdm的进度条会带来微小开销,不需要的话可以直接去掉。
  3. Dask并行处理(极端场景):如果数据量远超单机内存,可改用Dask DataFrame,它支持并行分块计算,语法与Pandas几乎一致,能突破单机内存限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:23:30