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

使用pandas时df.copy()结合remove为何会修改原DataFrame?

原因分析

问题核心出在原地修改列表对象的操作逻辑上:

  1. 虽然deepcopy或df.copy(deep=True)会递归复制DataFrame中的列表对象,但你使用new_df['name'][i].remove(j)是对列表进行原地修改,这种操作依赖于对象引用,一旦遍历逻辑出现异常(比如遍历列表的同时删除元素),再加上交互式环境中可能存在的变量复用问题,容易引发引用混淆,导致你误以为原df被修改。
  2. 更关键的是,Pandas的索引机制在处理object类型列时,直接原地修改元素可能会绕过深拷贝的隔离,出现意外的关联。
解决方法

不要原地修改列表,而是通过重新赋值新列表的方式修改副本,彻底切断与原df中列表对象的关联:

方法1:循环构造新列表并赋值

根据你想要保留的元素逻辑(原代码最终保留了列表的第2个元素),直接生成新列表并赋值给副本的对应单元格:

import pandas as pd
import copy

data = {"name": [["Sally", "EYE", "FACE"], ["Mary", "John"]],
        "qualified": [True, False]}
df = pd.DataFrame(data)
new_df = copy.deepcopy(df)

# 遍历副本,重新构造name列的列表
for i in range(len(new_df)):
    # 保留列表索引为1的元素(对应原代码的最终结果)
    new_list = [new_df['name'][i][1]]
    # 使用.loc赋值,确保修改的是副本的独立对象
    new_df.loc[i, 'name'] = new_list

print("\nNEWDF: ", new_df)
print("\nDF: ", df)

方法2:用apply生成新列

更简洁的方式是用apply直接生成新的name列,避免循环:

import pandas as pd
import copy

data = {"name": [["Sally", "EYE", "FACE"], ["Mary", "John"]],
        "qualified": [True, False]}
df = pd.DataFrame(data)
new_df = copy.deepcopy(df)

# 用apply生成新的name列,保留每个列表的第2个元素
new_df['name'] = new_df['name'].apply(lambda x: [x[1]])

print("\nNEWDF: ", new_df)
print("\nDF: ", df)

这两种方法都会生成全新的列表对象赋值给副本,彻底避免对原df中列表对象的任何修改,确保原df保持初始状态。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 19:03:03