【问题标题】:Checking whether data frame is copy or view in Pandas在 Pandas 中检查数据框是复制还是查看
【发布时间】:2015-01-08 20:08:00
【问题描述】:

是否有一种简单的方法可以检查两个数据帧是否是不涉及操作的相同基础数据的不同副本或视图?我试图掌握每个规则的生成时间,并且考虑到规则看起来有多么特殊,我想要一种简单的测试方法。

例如,我认为“id(df.values)”在各个视图中是稳定的,但它们似乎不是:

# Make two data frames that are views of same data.
df = pd.DataFrame([[1,2,3,4],[5,6,7,8]], index = ['row1','row2'], 
       columns = ['a','b','c','d'])
df2 = df.iloc[0:2,:]

# Demonstrate they are views:
df.iloc[0,0] = 99
df2.iloc[0,0]
Out[70]: 99

# Now try and compare the id on values attribute
# Different despite being views! 

id(df.values)
Out[71]: 4753564496

id(df2.values)
Out[72]: 4753603728

# And we can of course compare df and df2
df is df2
Out[73]: False

我查找的其他答案试图给出规则,但似乎不一致,也没有回答如何测试这个问题:

当然还有: - http://pandas.pydata.org/pandas-docs/stable/indexing.html#returning-a-view-versus-a-copy

更新: 下面的评论似乎回答了这个问题——查看df.values.base 属性而不是df.values 属性,以及对df._is_copy 属性的引用(尽管后者可能是非常糟糕的形式,因为它是内部的)。

【问题讨论】:

  • 嗯,df2._is_view 返回 True 但鉴于它被标记为私有/内部,可能有更好的方法来解决它。
  • 对于您的情况,您可以使用:df2.values.base is df.values.base
  • 一般来说,df.values 会创建一个副本,除非它是一个单一的 dtype(因为计算量很大)。你为什么要关心它是否是一个视图以及你实际上想要做什么?
  • 太棒了!感谢 HYRY 和 Marius!那些肯定会这样做——我没有发现 values.base,也不知道 _is_view 属性(尽管正如你所说,可能最好避免使用它,因为它是内部的)。
  • @HYRY 那么id's呢?如果只有一个对象,为什么它们会有所不同?还是视图是另一个对象?

标签: python pandas chained-assignment


【解决方案1】:

我已经用 pandas 1.0.1 详细说明了这个示例。不仅有一个布尔值_is_view 属性,还有_is_copy 可以是None 或对原始DataFrame 的引用:

df = pd.DataFrame([[1,2,3,4],[5,6,7,8]], index = ['row1','row2'], 
        columns = ['a','b','c','d'])
df2 = df.iloc[0:2, :]
df3 = df.loc[df['a'] == 1, :]

# df is neither copy nor view
df._is_view, df._is_copy
Out[1]: (False, None)

# df2 is a view AND a copy
df2._is_view, df2._is_copy
Out[2]: (True, <weakref at 0x00000236635C2228; to 'DataFrame' at 0x00000236635DAA58>)

# df3 is not a view, but a copy
df3._is_view, df3._is_copy
Out[3]: (False, <weakref at 0x00000236635C2228; to 'DataFrame' at 0x00000236635DAA58>)

因此,检查这两个属性不仅可以告诉您是否正在处理 view,还可以告诉您是否有副本或“原始”DataFrame。

另请参阅this thread,了解为什么您无法始终预测代码是否会返回视图的讨论。

【讨论】:

  • 请注意,_is_view 的文档说“如果我可能是视图,则返回布尔值”,所以我相信它可能会返回 False Negatives。有点像我在这个例子中使用它:foo = pd.Series(['a', 'b', 'c', 'd'], dtype='string'); bar = foo.iloc[:2]; bar._is_view; bar.iloc[0] = 'z'; print(foo)
【解决方案2】:

来自 HYRY 和 Marius 在 cmets 中的回答!

可以通过以下方式进行检查:

  • 测试values.base 属性而不是values 属性的等效性,如下所示:

    df.values.base is df2.values.base 而不是df.values is df2.values

  • 或使用(公认的内部)_is_view 属性(df2._is_viewTrue)。

谢谢大家!

【讨论】:

  • 如果关系是嵌套的怎么办?这仍然可以正常工作吗?也就是说,如果 DF1 可能是视图,则可能是 DF2 的副本;而 DF2 可能是一个视图,也可能是 DF3 的一个副本?
  • id's 呢?
【解决方案3】:

您可能会跟踪您的 pandas/python 环境正在消耗的内存,并且假设副本将使用比视图更多的内存,您可以决定一种或另一种方式。

我相信那里有一些库可以展示 python 环境本身的内存使用情况——例如海比/孔雀鱼。

应该有一个可以应用的度量标准,它在创建要检查的对象之前拍摄内存使用的基线图片,然后再拍摄另一张图片。比较两个内存映射(假设没有创建任何其他内容,并且我们可以隔离更改是由新对象引起的)应该可以了解是否已生成视图或副本。

我们需要了解每种实现类型的不同内存配置文件,但一些实验应该会产生结果。

【讨论】:

    猜你喜欢
    • 2020-12-31
    • 2022-07-21
    • 2018-07-11
    • 2021-06-26
    • 2017-02-15
    • 2019-05-07
    • 1970-01-01
    • 2016-08-01
    • 2021-10-23
    相关资源
    最近更新 更多