在文档上,它说
NDFrame的Numpy表示 - Source
" NDFrame的" Numpy表示"意思?修改这个numpy表示会影响我的原始数据帧吗?换句话说,将.values
返回副本或视图?
StackOverflow中有问题的答案隐式建议(依赖)返回视图。例如,在Set values on the diagonal of pandas.DataFrame的接受答案中,np.fill_diagonal(df.values, 0)
用于将df
的对角线部分上的所有值设置为0.这是在这种情况下返回的视图。但是,如@coldspeed's answer所示,有时会返回副本。
这感觉非常基本。这对我来说有点奇怪,因为我没有更详细的.values
来源。
另一个实验除了@ coldspeed的答案中的当前实验之外还返回一个视图:
df = pd.DataFrame([["A", "B"],["C", "D"]])
df.values[0][0] = 0
我们得到了
df
0 1
0 0 B
1 C D
即使它现在是混合类型,我们仍然可以通过设置df
来修改原始df.values
df.values[0][1] = 5
df
0 1
0 0 5
1 C D
答案 0 :(得分:9)
TL; DR:
如果返回副本(然后更改值不会更改DataFrame)或values
返回视图,则是实现细节(然后更改值将更改为DataFrame)。不要依赖这些情况中的任何一个。如果熊猫开发人员认为这将是有益的,那么它可能会改变(例如,如果他们改变了DataFrame的内部结构)。
我猜自问问题以来,文档已更改,目前显示为:
pandas.DataFrame.values
返回DataFrame的Numpy表示形式。
仅返回DataFrame中的值,将删除轴标签。
它不再提及NDFrame
,而只是提及“ DataFrame的NumPy表示形式”。 NumPy表示形式可以是视图或副本!
文档中还包含有关混合dtypes的Note
:
注释
dtype将是一个较低的公分母dtype(隐式向上转换);也就是说,如果dtypes(甚至是数字类型)混合在一起,则将选择容纳所有类型的dtypes。如果您不处理这些块,请小心使用。
例如如果dtype是float16和float32,则dtype将被向上转换为float32。如果dtype是int32和uint8,则dtype将被转换为int32。根据{{1}}的约定,将int64和uint64混合使用会产生float64 dtype。
从这些注释中很明显,访问包含不同dtypes的DataFrame的numpy.find_common_type()
可以(几乎)从不返回视图。仅仅是因为它需要将值放入“最低公分母” dtype的数组中,并且涉及一个副本。
但是它没有说明视图/复制行为,这是设计使然。 jreback在熊猫问题跟踪器 1 中提到,这确实只是实现细节:
这是一个实现细节。由于您将获得一个dtyped numpy数组,因此将其转换为兼容的dtype。如果您有混合dtype,则几乎总是会有一个副本(例外是混合浮动dtypes不会复制),但这是一个小细节。
我同意这不是很好,但是它从一开始就存在,并且不会在当前的大熊猫中改变。如果要导出到numpy,则需要保重。
即使values
的文档也没有提及视图:
Series
取决于dtype,返回系列为ndarray或类似ndarray
它甚至提到根据dtype可能甚至不返回纯数组。这当然包括它返回副本的可能性(即使只是假设)。它不能保证您得到视图。
pandas.Series.values
何时返回视图,何时返回副本?答案很简单:这是实现细节,只要是实现细节,就没有任何保证。它是实现细节的原因是,熊猫开发人员希望确定是否可以更改内部存储。 但是,在某些情况下,无法创建视图。例如,对于包含不同dtype列的DataFrame。
如果您分析迄今为止的行为,可能会有好处。但是,只要这是实现细节,您就不应该真的依赖它。
但是,如果您有兴趣:熊猫当前在内部存储与多维数组相同dtype的列。这样做的好处是,您可以非常高效地对行和列进行操作(至少只要它们具有相同的dtype)。但是,如果DataFrame包含混合类型,则它将具有多个内部多维数组。每个dtype一个。创建指向两个不同数组的视图是不可能的(至少对于NumPy而言),因此当您混合使用dtypes时,如果需要.values
,将获得一个副本。
旁注,例如:
values
不是混合dtype。它具有特定的dtype:df = pd.DataFrame([["A", "B"],["C", "D"]])
df.values[0][0] = 0
。但是object
数组可以包含任何Python对象,因此我可以理解为什么您会说/假设它是混合类型。
个人笔记:
就我个人而言,我更希望object
属性仅在无法返回视图时才返回视图或错误,以及仅返回副本的附加方法(例如values
),即使有可能得到一个看法。这肯定会使行为更加可预测,并避免出现意外情况,例如拥有财产进行昂贵的复制肯定是意外的。
1 这个问题已在问题发布中提到,因此文档可能因为这个问题而发生了变化。
答案 1 :(得分:7)
让我们测试一下。
首先,使用pd.Series
个对象。
In [750]: s = pd.Series([1, 2, 3])
In [751]: v = s.values
In [752]: v[0] = 10000
In [753]: s
Out[753]:
0 10000
1 2
2 3
dtype: int64
现在,对于DataFrame
个对象。首先,考虑非混合dtypes
-
In [780]: df = pd.DataFrame(1 - np.eye(3, dtype=int))
In [781]: df
Out[781]:
0 1 2
0 0 1 1
1 1 0 1
2 1 1 0
In [782]: v = df.values
In [783]: v[0] = 12345
In [784]: df
Out[784]:
0 1 2
0 12345 12345 12345
1 1 0 1
2 1 1 0
进行了修改,因此意味着.values
返回了一个视图。
现在,考虑混合dtypes
-
In [755]: df = pd.DataFrame({'A' :[1, 2], 'B' : ['ccc', 'ddd']})
In [756]: df
Out[756]:
A B
0 1 ccc
1 2 ddd
In [757]: v = df.values
In [758]: v[0] = 123
In [759]: v[0, 1] = 'zzxxx'
In [760]: df
Out[760]:
A B
0 1 ccc
1 2 ddd
此处,.values
会返回副本。
<强>观察强>
对于Series, .values
会返回一个视图,而不管每行的dtypes,而对于DataFrames,这取决于。对于同质dtypes,返回视图。否则,副本。