【问题标题】:Truly deep copying Pandas DataFrames真正深度复制 Pandas 数据帧
【发布时间】:2021-02-22 15:01:42
【问题描述】:

我遇到了一件我觉得很奇怪的事情:显然,要真正深度复制 pandas 数据帧是不可能的。

我希望,如果我创建一个数据帧的深层副本,并修改此副本中的数据,它不会影响原始数据帧。但显然情况并非如此,如果我没记错的话,甚至是可能的。

要重现的代码:

import pandas as pd

df = pd.DataFrame({'sets':set([1,2])}, index=[0])

def pop(df_in):
    df = df_in.copy()
    print(df['sets'].apply(lambda x: set([x.pop()])))

pop(df)
pop(df)
pop(df)

>>> KeyError: 'pop from an empty set'

import copy
import pandas as pd

df = pd.DataFrame({'sets':set([1,2])}, index=[0])

def pop(df_in):
    df = copy.deepcopy(df_in)
    print(df['sets'].apply(lambda x: set([x.pop()])))

pop(df)
pop(df)
pop(df)

>>> KeyError: 'pop from an empty set'

我的问题是:

  1. 是否可以创建真正的 pandas 数据帧的深层副本?
  2. 如果不是,为什么?如果是,怎么做?

【问题讨论】:

  • 顺便说一句,在数据框中有集合是很奇怪的。

标签: python pandas dataframe deep-copy


【解决方案1】:

一种方法是将df_in 转换为与copy 配合使用的Python 字典:

def pop(df_in):
    df = pd.DataFrame(copy.deepcopy(df_in.to_dict()) )
    print(df['sets'].apply(lambda x: set([x.pop()])))

for i in range(3): pop(df)

输出:

0    {1}
Name: sets, dtype: object
0    {1}
Name: sets, dtype: object
0    {1}
Name: sets, dtype: object

【讨论】:

    【解决方案2】:

    问题在于您的对象是可变,因为它们是集合。 documents 明确指出此行为并发出警告(强调我自己的):

    当 deep=True 时,复制数据但不会递归复制实际的 Python 对象,只会复制对对象的引用。

    因此,与对可变对象的引用一样,如果您更改它,它会在任何地方影响它。尽管对象具有相同的 ID,但我们可以自己查看。

    import pandas as pd
    df = pd.DataFrame({'sets': [{1,2}]}, index=[0])
    df1 = df.copy(deep=True)
    
    id(df['sets'].iloc[0])
    #4592957024
    
    id1(df['sets'].iloc[0])
    #4592957024
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-20
      • 1970-01-01
      • 2020-09-22
      • 2015-09-08
      • 2020-11-21
      • 2023-03-27
      • 2019-10-14
      • 2021-11-16
      相关资源
      最近更新 更多