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

为Pandas DataFrame批量添加列遇性能警告,求pd.concat正确用法

问题场景

我尝试通过以下代码给Pandas DataFrame批量添加求和列:

def create_sum_rounds(df, col_name_base):
    '''
    根据基础列生成求和列。示例:
    df['sum_foo'] = df['foo_1'] + df['foo_2'] + df['foo_3'] + \
                    df['foo_4'] + df['foo_5']
    '''
    out_name = 'sum_' + col_name_base
    df[out_name] = 0.0
    for i in range(1, 6):
        col_name = col_name_base + str(i)
        if col_name in df:
            df[out_name] += df[col_name]
        else:
            logger.error('列 %s 不存在于DataFrame中' % col_name)

for col in sum_cols_list:
    create_sum_rounds(df, col)

其中sum_cols_list是包含约200个基础列名(如"foo")的列表,df包含对应基础列扩展出的"foo_1", "foo_2", ..., "foo_5"这类列。

运行代码时收到性能警告:

PerformanceWarning: DataFrame is highly fragmented.  This is usually the result of calling `frame.insert` many times, which has poor performance.  Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()`

我猜测这是因为循环添加新列时后台频繁调用insert导致的。请问此时正确使用pd.concat的方式是什么?


优化方案:使用pd.concat批量生成并合并列

核心思路是先批量生成所有需要的求和列,再一次性合并到原DataFrame,避免循环中逐列插入的性能损耗。

具体实现步骤

  • 先创建一个临时容器(DataFrame或Series列表)存储所有待新增的求和列
  • 遍历sum_cols_list,计算每个基础列对应的求和结果,存入临时容器
  • 最后用pd.concat将原DataFrame和临时容器中的列一次性合并

优化后的代码

import pandas as pd

# 初始化临时DataFrame存储所有求和列
sum_cols_df = pd.DataFrame()

for col_base in sum_cols_list:
    out_col_name = f'sum_{col_base}'
    # 生成当前基础列对应的_round列名列表
    target_cols = [f'{col_base}_{i}' for i in range(1, 6)]
    # 过滤出DataFrame中实际存在的列
    existing_cols = [col for col in target_cols if col in df.columns]
    
    if existing_cols:
        # 直接对行求和生成新列
        sum_cols_df[out_col_name] = df[existing_cols].sum(axis=1)
    else:
        logger.error(f'基础列 {col_base} 对应的_round列均不存在')

# 一次性合并原DataFrame和所有求和列
df = pd.concat([df, sum_cols_df], axis=1)

额外优化细节

  • 用df.columns判断列存在性比col in df更高效
  • 利用Pandas原生的sum(axis=1)替代循环累加,代码更简洁且性能更优
  • 如果担心内存占用,也可以用列表存储单个Series,最后再合并:
    sum_series_list = []
    for col_base in sum_cols_list:
        out_col_name = f'sum_{col_base}'
        target_cols = [f'{col_base}_{i}' for i in range(1, 6)]
        existing_cols = [col for col in target_cols if col in df.columns]
        
        if existing_cols:
            sum_series = df[existing_cols].sum(axis=1).rename(out_col_name)
            sum_series_list.append(sum_series)
        else:
            logger.error(f'基础列 {col_base} 对应的_round列均不存在')
    
    df = pd.concat([df] + sum_series_list, axis=1)
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 23:19:01