gpt4 book ai didi

python - pandas dataframe View 与复制,我如何区分?

转载 作者:太空宇宙 更新时间:2023-11-03 21:26:49 25 4
gpt4 key购买 nike

有什么区别:

pandas df.loc[:,('col_a','col_b')]

df.loc[:,['col_a','col_b']]

下面的链接没有提到后者,尽管它有效。两者都拉 View 吗?第一个拉取 View ,第二个拉取副本吗?

http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy

最佳答案

如果您的 DataFrame 有一个简单的列索引,则没有区别。例如,

In [8]: df = pd.DataFrame(np.arange(12).reshape(4,3), columns=list('ABC'))

In [9]: df.loc[:, ['A','B']]
Out[9]:
A B
0 0 1
1 3 4
2 6 7
3 9 10

In [10]: df.loc[:, ('A','B')]
Out[10]:
A B
0 0 1
1 3 4
2 6 7
3 9 10

但是如果 DataFrame 具有 MultiIndex,则可能会有很大差异:

df = pd.DataFrame(np.random.randint(10, size=(5,4)),
columns=pd.MultiIndex.from_arrays([['foo']*2+['bar']*2,
list('ABAB')]),
index=pd.MultiIndex.from_arrays([['baz']*2+['qux']*3,
list('CDCDC')]))

# foo bar
# A B A B
# baz C 7 9 9 9
# D 7 5 5 4
# qux C 5 0 5 1
# D 1 7 7 4
# C 6 4 3 5

In [27]: df.loc[:, ('foo','B')]
Out[27]:
baz C 9
D 5
qux C 0
D 7
C 4
Name: (foo, B), dtype: int64

In [28]: df.loc[:, ['foo','B']]
KeyError: 'MultiIndex Slicing requires the index to be fully lexsorted tuple len (1), lexsort depth (0)'

KeyError 表示必须对 MultiIndex 进行词法排序。如果我们这样做,那么我们仍然会得到不同的结果:

In [29]: df.sortlevel(axis=1).loc[:, ('foo','B')]
Out[29]:
baz C 9
D 5
qux C 0
D 7
C 4
Name: (foo, B), dtype: int64

In [30]: df.sortlevel(axis=1).loc[:, ['foo','B']]
Out[30]:
foo
A B
baz C 7 9
D 7 5
qux C 5 0
D 1 7
C 6 4

这是为什么呢? df.sortlevel(axis=1).loc[:, ('foo','B')] 正在选择第一个列级别等于 foo 的列,并且第二列级别是 B

相反,df.sortlevel(axis=1).loc[:, ['foo','B']] 选择第一个列级别为 的列fooB。对于第一列级别,没有 B 列,但有两个 foo 列。

我认为 Pandas 的操作原理是,如果你使用 df.loc[...] 作为一个表达式,您应该假设df.loc可能返回一个副本或 View 。 Pandas 文档没有指定任何您应该期望的规则。但是,如果您对表单进行分配

df.loc[...] = value

那么你就可以相信 Pandas 会改变 df 本身。

文档警告 View 和副本之间的区别的原因是为了让您意识到使用以下形式的链分配的陷阱

df.loc[...][...] = value

在这里,Pandas 首先评估 df.loc[...],它可能是 View 或副本。现在如果它是一个副本,那么

df.loc[...][...] = value

正在更改df某些部分的副本,因此对df本身没有影响。雪上加霜的是,对副本的影响也会丢失,因为没有对副本的引用,因此在赋值语句完成后无法访问副本,并且(至少在 CPython 中)因此很快-待垃圾收集。

<小时/>

我不知道一种实用的万无一失的先验方法来确定df.loc[...]是否将返回 View 或副本。

但是,有一些经验法则可能有助于指导您的直觉(但请注意,我们在这里讨论的是实现细节,因此不能保证 Pandas 将来需要这样做):

  • 如果生成的 NDFrame 不能表示为 NDFrame 的基本切片底层 NumPy 数组,那么它可能是一个副本。因此,选择任意行或列将产生一个副本。连续行和/或连续列(可以表示为切片)的选择可以返回 View 。
  • 如果生成的 NDFrame 具有不同数据类型的列,则 df.loc可能会再次返回一份副本。

但是,有一种简单的方法可以确定 x = df.loc[..] 是否为 View 事后:只需查看是否更改 x 影响 df。如果是,则它是一个 View ,如果不是,则 x 是一个副本。

关于python - pandas dataframe View 与复制,我如何区分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53788871/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com