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

Pandas 2.x中使用zip循环后输出DataFrame为空的解决方法

Pandas 2.x中循环zip操作DataFrame赋值失效问题解决

问题背景

将旧的Pandas 1.x代码升级到2.x后,尝试通过zip()循环将输入DataFrame复制到输出DataFrame时遇到问题:循环结束后输出DataFrame(dfo1、dfo2)仍为空,无法保留循环内的赋值操作。核心疑问是:使用zip()时,如何在循环内正确复制DataFrame,让全局的输出DataFrame在循环后可正常使用?

测试代码

import numpy as np
import pandas as pd

data=np.random.randn(24).reshape(6,4)
df=pd.DataFrame(data,index=['1','2','3','4','5','6'],columns=['A','B','C','D'])

data2=np.random.randn(24).reshape(6,4)
df2=pd.DataFrame(data,index=['1','2','3','4','5','6'],columns=['A','B','C','D'])

dflist=[df,df2] # 输入DataFrame列表

print(f'Address of df is:{hex(id(df))}, and df2 is:{hex(id(df2))}')

# 初始化空的输出DataFrame
dfo1=pd.DataFrame()
dfo2=pd.DataFrame()
dfout=[dfo1,dfo2]

print(f'Address of dfo1 is:{hex(id(dfo1))}, and dfo2 is:{hex(id(dfo2))}')


print('***Begin Loop')
for i,(dfo,dfx) in enumerate(zip(dfout,dflist)):
    print(f'\ti={i}')
    print(f'\t**Start of loop:  Address of dfo is:{hex(id(dfo))}. Address of dfx is:{hex(id(dfx))} ')
    dfx.iloc[3,3]=0 # 测试修改输入DataFrame
    
    # 尝试的赋值方式均未生效
    # dfo=dfx.copy()
    # dfo.append(dfx)  # Pandas 1.x可用,2.x已移除
    dfo=pd.concat([dfo,dfx]) 

    dfo.iloc[0,0]=99 # 测试修改输出DataFrame
    print(f'\t**End of loop:  Address of dfo is:{hex(id(dfo))}. Address of dfx is:{hex(id(dfx))} ')
    print(f'\tdfx shape is{dfx.shape}')
    print(f'\tdfo shape is{dfo.shape}')
    print(dfo)

# 循环后dfo1仍为空
print(f'Address of dfo1 is: {hex(id(dfo1))}')
print(f'dfo1 shape after loop is{dfo1.shape}') # 输出(0,4)
dfo1   

问题根源

循环中dfo是从dfout列表中取出的局部变量,当执行dfo = pd.concat([dfo, dfx])时,并不是修改原来的空DataFrame对象,而是创建了一个新的DataFrame对象,并让局部变量dfo指向这个新对象。原来的dfout列表中的元素(即全局的dfo1、dfo2)并没有被修改,它们仍然指向最初的空DataFrame,所以循环结束后dfo1、dfo2还是空的。

解决方法

方法1:直接修改输出列表dfout的元素

循环中不直接给局部变量dfo赋值,而是通过索引修改dfout列表对应的位置,让其指向新的DataFrame对象:

print('***Begin Loop')
for i,(dfo,dfx) in enumerate(zip(dfout,dflist)):
    print(f'\ti={i}')
    print(f'\t**Start of loop:  Address of dfo is:{hex(id(dfo))}. Address of dfx is:{hex(id(dfx))} ')
    dfx.iloc[3,3]=0
    
    # 直接修改dfout列表的对应元素
    new_dfo = pd.concat([dfo, dfx])
    new_dfo.iloc[0,0] = 99
    dfout[i] = new_dfo  # 关键:更新列表中的元素
    
    print(f'\t**End of loop:  Address of new_dfo is:{hex(id(new_dfo))} ')
    print(f'\tdfx shape is{dfx.shape}')
    print(f'\tnew_dfo shape is{new_dfo.shape}')
    print(new_dfo)

# 循环后更新dfo1和dfo2
dfo1, dfo2 = dfout
print(f'Address of dfo1 is: {hex(id(dfo1))}')
print(f'dfo1 shape after loop is{dfo1.shape}') # 输出(6,4)
dfo1

方法2:预先不创建空DataFrame,直接生成输出列表

如果不需要保留初始的空DataFrame,可以直接在循环中构建新的输出列表,避免局部变量与全局变量的混淆:

dfout = []
for dfx in dflist:
    dfx.iloc[3,3] = 0
    dfo = pd.concat([pd.DataFrame(), dfx])
    dfo.iloc[0,0] = 99
    dfout.append(dfo)

dfo1, dfo2 = dfout
print(f'dfo1 shape after loop is{dfo1.shape}') # 输出(6,4)
dfo1

补充说明

  • Pandas 2.x中已移除DataFrame.append()方法,官方推荐使用pd.concat()替代,这部分你的方向是对的,问题出在变量赋值的逻辑上,而非concat()的用法。
  • 若需要深拷贝DataFrame(避免后续修改输入DataFrame影响输出),可以在赋值时使用dfx.copy(deep=True),比如new_dfo = pd.concat([dfo, dfx.copy(deep=True)])。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 03:42:24