DataFrame.values中的更改是否总是会修改数据框中的值?

Tai*_*Tai 11 python numpy dataframe pandas

它说,在文档上

NDFrame的Numpy表示 - 来源

"NDFrame的Numpy表示"是什么意思?修改这个numpy表示会影响我的原始数据帧吗?换句话说,.values返回副本还是视图

StackOverflow中有问题的答案隐含地建议(依赖)返回视图.例如,在pandas.DataFrame的对角线上的Set值的接受答案中,np.fill_diagonal(df.values, 0)用于将对角线部分的所有值设置df为0.这是在这种情况下返回的视图.但是,如@coldspeed的回答所示,有时会返回副本.

这感觉非常基本.这对我来说有点奇怪,因为我没有更详细的资料来源.values.


另一个实验除了@ coldspeed的回答中的当前实验之外还返回一个视图:

df = pd.DataFrame([["A", "B"],["C", "D"]])

df.values[0][0] = 0
Run Code Online (Sandbox Code Playgroud)

我们得到了

df
    0   1
0   0   B
1   C   D
Run Code Online (Sandbox Code Playgroud)

即使它现在是混合型,我们仍然可以df通过设置修改原件df.values

df.values[0][1] = 5
df
    0   1
0   0   5
1   C   D
Run Code Online (Sandbox Code Playgroud)

MSe*_*ert 10

TL; DR:

如果返回副本(然后更改值不会更改DataFrame)或values返回视图(然后更改值更改DataFrame),这是一个实现细节.不要依赖任何这些案件.如果大熊猫开发人员认为它会有所帮助(例如,如果他们改变了DataFrame的内部结构),它可能会改变.


我想自问题被问到后文档已经改变,目前它的内容如下:

pandas.DataFrame.values

返回DataFrame的Numpy表示.

只返回DataFrame中的值,轴标签将被删除.

它不再提及NDFrame了 - 但只是简单地提到了"DataFrame的NumPy表示".NumPy表示可以是视图或副本!

该文档还包含Note有关混合dtypes的信息:

笔记

dtype将是一个较低的共同分母dtype(隐式向上转换); 也就是说,如果dtypes(甚至是数字类型)混合在一起,那么将选择容纳所有dtypes的那个.如果您不处理块,请小心使用它.

例如,如果dtypes是float16和float32,则dtype将向上转换为float32.如果dtypes是int32和uint8,则dtype将向上转换为int32.按照numpy.find_common_type()惯例,混合int64和uint64将导致float64 dtype.

从这些Notes中可以看出,访问values包含不同dtypes的DataFrame可以(几乎)永远不会返回视图.仅仅因为它需要将值放入"最低公分母"dtype的数组中并且涉及副本.

但是它没有说明视图/复制行为和设计的任何内容.在pandas问题跟踪器1上提到的jreback,这实际上只是一个实现细节:

这是一个实现细节.因为你得到一个dtyped numpy数组,所以它是upcast到兼容的dtype.如果你有混合dtypes,那么你几乎总是会有一个副本(混合浮动dtypes不会复制我认为),但这是一个numpy细节.

我同意这不是很好,但它从一开始就存在,并且不会改变当前的大熊猫.如果输出到numpy,你需要小心.

甚至文档Series中也没有提及视图:

pandas.Series.values

返回系列为ndarray或ndarray-like取决于dtype

它甚至提到它甚至可能不会返回一个普通的数组,具体取决于dtype.这肯定包括它返回副本的可能性(即使它只是假设).它不能保证您获得视图.


何时.values返回视图以及何时返回副本?

答案很简单:这是一个实现细节,只要它是一个实现细节,就不会有任何保证.它是一个实现细节的原因是因为大熊猫开发人员希望确保他们可以根据需要更改内部存储.但是在某些情况下,无法创建视图.例如,使用包含不同dtypes列的DataFrame.

如果分析迄今为止的行为,可能会有一些优势.但只要这是一个实现细节,你就不应该真正依赖它.

但是,如果您感兴趣:Pandas 目前在内部存储具有相同dtype的列作为多维数组.这样做的好处是,您可以非常有效地操作行和列(至少只要它们具有相同的dtype).但是如果DataFrame包含混合类型,它将具有多个内部多维数组.每个dtype一个.创建一个指向两个不同数组的视图是不可能的(至少对于NumPy而言),所以当你有混合dtypes时,你会得到一个你想要的副本values.


旁注,你的例子:

df = pd.DataFrame([["A", "B"],["C", "D"]])

df.values[0][0] = 0
Run Code Online (Sandbox Code Playgroud)

不是混合型.它有一个特定的dtype : object. 但是object数组可以包含任何Python对象,所以我可以看到为什么你会说/假设它是混合类型.


个人说明:

就个人而言,我希望该values属性只有在它无法返回视图时才会返回视图或错误,并且即使可以获得视图as_array也只返回副本的其他方法(例如).这肯定会使行为更加可预测,并避免一些意外,例如让财产做昂贵的副本肯定是出乎意料的.


1问题帖子中已经提到过这个问题,因此可能因为这个问题而改变了文档.


cs9*_*s95 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
Run Code Online (Sandbox Code Playgroud)

现在,对于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
Run Code Online (Sandbox Code Playgroud)

进行修改,以便.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
Run Code Online (Sandbox Code Playgroud)

在这里,.values返回一份副本.


意见

.values对于Series,无论每行的dtypes如何都返回一个视图,而对于DataFrames,这取决于.对于同质dtypes,返回视图.否则,副本.

  • 找到了一个很好的实验的反例!往上看. (2认同)
  • @cᴏʟᴅsᴘᴇᴇᴅ据我所知,因为它也可以用一个numpy数组来表示它不是免税但我不能100%肯定. (2认同)