分配给值时的行为为何不一致?

piR*_*red 3 python numpy dataframe pandas

考虑两个DataFrames d1d2:

d1 = pd.DataFrame(np.arange(2).reshape(-1, 2), columns=['A', 'B'])
d2 = pd.DataFrame(dict(A=[0], B=list('a')))
Run Code Online (Sandbox Code Playgroud)

我想覆盖第一列d1.它开始于:

d1

   A  B
0  0  1
Run Code Online (Sandbox Code Playgroud)

我试图覆盖以下的值'A':

d1.values[:, 0] = 2
d1

   A  B
0  2  1
Run Code Online (Sandbox Code Playgroud)

但是当我做同样的事情时d2,我会得到不同的结果.

d2

   A  B
0  0  a
Run Code Online (Sandbox Code Playgroud)

然后:

d2.values[:, 0] = 2
d2

   A  B
0  0  a
Run Code Online (Sandbox Code Playgroud)

没有什么改变,除非我这样做:

d2.A.values[:] = 2
d2

   A  B
0  2  a
Run Code Online (Sandbox Code Playgroud)

为什么这种行为不一致?

MSe*_*ert 6

由于混合dtypes,当你访问整个时,d2你会得到一个object-array(copy).values.

>>> d2.values
array([[0, 'a']], dtype=object)
Run Code Online (Sandbox Code Playgroud)

对于任何不相同的数据类型都会发生这种情况,例如int32对于int64:

>>> d2 = pd.DataFrame(dict(A=np.int32([0]), B=np.int64([0])))
>>> d2.values[:, 1] = 3
>>> print(d2)
   A  B
0  0  0
Run Code Online (Sandbox Code Playgroud)

如果所有列的dtype完全相同,则更改仅传播回:

>>> d2 = pd.DataFrame(dict(A=np.int32([0]), B=np.int32([0])))
>>> d2.values[:, 1] = 3
>>> print(d2)
   A  B
0  0  3
Run Code Online (Sandbox Code Playgroud)

只是给出(近似)方式来确定它是否是您可以使用的实际列的视图或副本np.shares_memory:

>>> np.shares_memory(d1.values, d1.A.values)
True

>>> np.shares_memory(d2.values, d2.A.values)
False
Run Code Online (Sandbox Code Playgroud)

  • 是的,pandas通常将它们保存在单独的块中(int在它自己的数组中,对象在它自己的数组中)但是当你调用values属性时,它会在dtypes混合时创建一个numpy数组(副本). (2认同)