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

Pandas DataFrame批量新增列如何避免碎片化导致对象为None

根因分析

PerformanceWarning: DataFrame is highly fragmented本身属于性能提示,不会直接导致DataFrame变为None,该异常是高频逐列插入触发的pandas旧版本边界bug:

  • 每次通过df[col_name] = value语法新增列时,pandas都会在底层拆分独立内存块存储新列。当前逻辑需要循环生成39*13=507个新列,逐次插入会产生数百个零散内存块,除了运行速度指数级下降外,在pandas 1.x~2.0早期版本中,当内存块数量超过内部处理阈值时,列赋值操作会出现静默失败,最终导致整个df对象返回None。
  • 循环中插入df = df.copy()无法解决问题:如果copy操作执行在赋值失败的节点之后,拿到的本身就是已经异常的对象;且DataFrame处于高度碎片化状态时,copy操作本身也可能触发相同的内部处理异常。
修复方案

按照警告提示调整实现逻辑,不要逐次往原df插入新列,先批量计算所有待新增列,再一次性拼接即可,同时可以优化原代码中的重复计算逻辑进一步提升效率:

import pandas as pd

Bbands_list = [-3,-2.5,-2,-1.5,-1,0,-0.5,0.5,1,1.5,2,2.5,3]
SMA_list = [1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,21,22,24,26,28,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,125,150,175,200]

new_columns = {}
for m in SMA_list:
    # 同一滚动窗口的均值、标准差仅计算1次,消除原逻辑中每个b值重复计算滚动统计量的冗余
    rolling_mean = df['Close'].rolling(m).mean()
    rolling_std = df['Close'].rolling(m).std()
    for b in Bbands_list:
        col_name = f"M{m}B{b}"
        new_columns[col_name] = (rolling_mean + rolling_std * b - df['Close']) / df['Close']

# 一次性拼接所有新列,从根源避免逐次插入导致的内存碎片化
df = pd.concat([df, pd.DataFrame(new_columns, index=df.index)], axis=1)
  • 上述写法完全规避了逐次插入列的操作,不会触发碎片化警告,运行效率比原循环写法高5~10倍,也不会出现赋值静默失败的问题。
  • 若当前使用的pandas版本低于2.0,建议升级到2.0以上稳定版,新版本重构了DataFrame底层存储逻辑,大幅降低了逐列插入的碎片化概率,同时修复了旧版本中赋值操作静默返回None的边界bug。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:31:09