Pandas中修改DataFrame自动同步到原DataFrame的原因与规避方法
该现象和Pandas无关、和你使用的Spyder IDE也无关,是Python通用的对象引用机制导致的,属于Python的标准行为。
你代码里写的Df1 = Df0并没有创建新的DataFrame对象,只是给内存中已经存在的同一个DataFrame额外绑定了一个名为Df1的变量别名。Df0和Df1从始至终指向内存里的同一个对象,不管你通过哪个变量名修改对象的属性、调整内部数据,另一个变量访问时都会读到改动后的结果。
这和你熟悉的R语言赋值逻辑有本质区别:R中默认赋值会生成对象的独立副本,修改新变量不会影响原对象;但Python中对可变对象的直接赋值不会触发拷贝,只会新增一个指向原对象的引用。
这个特性对所有Python可变对象都生效,不止是DataFrame,列表、字典、自定义类的实例直接用等号赋值,都会出现“修改新变量同步影响原变量”的情况。
你可以用Python内置的id()函数查看两个变量指向的内存地址,就能直观确认两者是同一个对象:
import pandas as pd Df0 = pd.DataFrame({'Col0': [1,2,3], 'Col1': [4,5,6]}) Df1 = Df0 print(id(Df0) == id(Df1)) # 执行后输出为True,证明两个变量指向完全相同的内存对象
如果需要获得和原DataFrame内容一致、但完全独立的新对象,不要直接用等号赋值,要根据你的数据结构显式调用拷贝方法:
- 浅拷贝:如果你的DataFrame中没有嵌套的可变对象(比如单元格内存储列表、字典这类可变结构),可以用浅拷贝模式,性能开销更小:
# 浅拷贝仅拷贝DataFrame的轴结构,不递归拷贝内部数据 Df1 = Df0.copy(deep=False) - 深拷贝:如果DataFrame中存在嵌套的可变对象,使用默认的深拷贝模式即可,会递归拷贝所有层级的内容,新对象和原对象完全隔离,后续任何修改都不会互相影响:
# 深拷贝是.copy()方法的默认行为,等价于Df0.copy(deep=True) Df1 = Df0.copy()
完成拷贝后再给Df1添加自定义属性、修改数据,都不会同步改动原Df0的内容。
补充说明:Pandas本身支持给DataFrame动态挂载自定义属性,但要注意Pandas绝大多数内置数据操作(比如筛选、分组、拼接、计算生成新表)默认都会返回全新的对象,不会原地修改原数据;只有你明确传入inplace=True参数调用方法时,才会直接改动原对象。
内容的提问来源于stack exchange,提问作者Paison Tiunn

