我需要对 pandas DataFrame() 执行一些操作以评估某些度量,但让我的 DataFrame 保持原样。所以我认为我应该从在内存中复制它开始:
import pandas as pd
df1 = pd.DataFrame({'a':[1,2,3]})
df2 = pd.DataFrame(df1)
打印时
print(id(df1), id(df2))
我确实得到了两个不同的系统地址。所以在我看来,这是 DataFrame() 的两个不同实例。
但是,如果我这样做:
df2['b'] = [4,5,6]
print(df1)
df1 出现时带有“b”列,尽管我只在 df2 中添加了它。
为什么会这样? 我怎样才能真正复制我的 DataFrame 以便对一个的操作不会修改另一个? 我在 Python 3.5 和 pandas 0.24.2
最佳答案
您需要使用 pd.DataFrame.copy
df2 = df1.copy()
一个赋值,即使你赋值给一个新变量,也会引用内存中的相同数据/索引,这意味着对 df1 或 df2 的操作将改变内存中的相同数据。然而,使用复制,df2 获得了自己的数据副本,可以独立操作。
解释:
为什么在 DataFrame
上调用 pd.DataFrame
时会得到两个不同的内存地址?
简单地说,pandas.DataFrame
是 numpy.ndarry
的包装器。当您使用 df1
数据帧作为输入调用 pd.DataFrame
时,会创建一个新的 pd.DataFrame
包装器(因此不同的内存地址),但数据完全相同。您可以使用以下代码验证:
In [2]: import pandas as pd
...: df1 = pd.DataFrame({'a':[1,2,3]})
...: df2 = pd.DataFrame(df1)
...:
In [3]: print(id(df1), id(df2))
(4665009296, 4665009360)
In [4]: df1._data
Out[4]:
BlockManager
Items: Index([u'a'], dtype='object')
Axis 1: RangeIndex(start=0, stop=3, step=1)
IntBlock: slice(0, 1, 1), 1 x 3, dtype: int64
In [5]: id(df1._data)
Out[5]: 4522343248
In [6]: id(df2._data)
Out[6]: 4522343248
如您所见,df1._data
和df2._data
的内存地址完全相同。
这个看DataFrame
源码也清楚in github ,其中,在构造函数的开头,新数据帧引用相同的数据:
if isinstance(data, DataFrame):
data = data._data
关于python - pandas DataFrame 中的内存处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55812035/