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

pd.DataFrame传入已有DataFrame的行为及相关技术疑问

Pandas浅拷贝与对象引用问题解析

先把你的测试代码贴出来方便对照:

In [1]: import pandas as pd
In [2]: a = pd.DataFrame(dict(a=[1,2,3], b=[4,5,6]))
In [3]: b = pd.DataFrame(a)
In [4]: a['c'] = [7,8,9]
In [5]: a
Out[5]: 
   a  b  c
0  1  4  7
1  2  5  8
2  3  6  9
In [6]: b
Out[6]: 
   a  b  c
0  1  4  7
1  2  5  8
2  3  6  9
In [7]: a.drop(columns='c', inplace=True)
In [8]: a
Out[8]: 
   a  b
0  1  4
1  2  5
2  3  6
In [9]: b
Out[9]: 
   a  b  c
0  1  4  7
1  2  5  8
2  3  6  9

问题拆解与解答

1. pd.DataFrame(a)的行为,以及a和b是不是同一对象?

首先明确:a和b是完全不同的DataFrame对象(你已经通过id验证了这一点),但它们在创建初期共享了内部的数据存储,这是Pandas默认的**浅拷贝(shallow copy)**机制导致的:

  • 当你用pd.DataFrame(a)创建b时,Pandas会生成一个新的DataFrame实例(所以id不同),但它不会完全复制a的所有数据,而是复用a的底层数据块和列结构引用。
  • 简单说:b是新的"外壳",但里面装的"数据内容"和a共用同一份。这就解释了为什么给a新增列c时,b也会同步出现这个列——因为你修改的是那份共享的数据内容,两个"外壳"都能看到变化。

2. 为什么删列时b不同步?

a.drop(columns='c', inplace=True)这个操作的本质和加列不一样:

  • 加列是直接在共享的数据存储里新增内容,所有引用它的对象都会看到变化;
  • 而原地删列操作,并不是直接修改共享的数据存储,而是重新创建了一个不包含c列的新数据存储,然后替换掉a自己的"数据内容"引用。这时候b的"数据内容"还是原来那份包含c列的旧存储,所以不会跟着删列。

3. 如何让a删列时b同步删除?

如果想要a和b完全同步任何操作,根本不需要创建新对象,直接让b成为a的引用即可:

b = a  # 直接赋值,此时a和b指向同一个DataFrame对象

这样不管是加列、删列还是修改单元格数据,a和b的表现都会完全一致,因为它们本质上是同一个对象的两个名字而已。

4. 如何避免加列时b同步新增?

要让a和b彻底独立,互不影响,需要创建深拷贝(deep copy),也就是完全复制a的所有数据和结构,生成一个完全独立的新对象:

# 两种写法都可以
b = pd.DataFrame(a, copy=True)
# 或者更直观的
b = a.copy(deep=True)

之后不管a做任何修改(加列、删列、改数据),b都不会受到任何影响,因为它有自己独立的数据存储了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 09:37:29