为什么 `.rename(columns={'b': 'b'}, copy=False)` 后使用 inplace 方法不更新原始数据框?

3 投票
2 回答
124 浏览
提问于 2025-04-14 15:36

这是我的例子:

In [1]: import pandas as pd

In [2]: df = pd.DataFrame({'a': [1,2,3], 'b': [4,5,6]})

In [3]: df1 = df.rename(columns={'b': 'b'}, copy=False)

In [4]: df1.isetitem(1, [7,8,9])

In [5]: df
Out[5]:
   a  b
0  1  4
1  2  5
2  3  6

In [6]: df1
Out[6]:
   a  b
0  1  7
1  2  8
2  3  9

如果df1是从df生成的,并且设置了copy=False,那么我本来以为对df1的直接修改也会影响到df。可是实际上并没有。为什么呢?

我使用的是pandas版本2.2.1,没有启用任何选项(比如说写时复制)

2 个回答

0

这段内容讲的是Python如何处理不可变和可变对象。

选项 copy=False 只是控制数据框(dataframe)内部的数据是否被复制,而不是控制整个数据框本身。

因此,rename 函数会创建一个新的 pd.DataFrame 对象 df1,这个新对象可能会和 df 共享数据,因为 copy=False。不过,它仍然是一个不同的数据框对象。

如果你想同时修改这两个数据框,可以这样做:

df.iloc[1] = [7, 8, 9]

这样做会同时修改 dfdf1

1

copy=False 的意思是底层的数据(numpy数组)是共享的。

如果我们修改了底层numpy数组中的某个元素,这个修改会被反映出来,因为数据是共享的:

df = pd.DataFrame({'a': [1,2,3], 'b': [4,5,6]})
df1 = df.rename(columns={'b': 'c'}, copy=False)
df1.values[0, 1] = 999

print(df)
   a    b
0  1  999
1  2    5
2  3    6

print(df1)
   a    c
0  1  999
1  2    5
2  3    6

print(id(df.values), id(df1.values))
# 140335530654768 140335530654768

不过,DataFrame对象(比如容器、索引、列名等)并不是完全相同的。

print(id(df), id(df1))
# 140335696175520 140335696171536

通过使用 df1.isetitem(1, [7,8,9]) 设置一个新列,你实际上是添加了一个新的Series,并强制进行了复制。

撰写回答