为什么 `.rename(columns={'b': 'b'}, copy=False)` 后使用 inplace 方法不更新原始数据框?
这是我的例子:
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]
这样做会同时修改 df
和 df1
。
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,并强制进行了复制。