2017-08-30 77 views
3

考虑两个DataFrames d1d2为什么分配值不一致时的行为?

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

我希望覆盖的d1第一列。

d1 

    A B 
0 0 1 

我试图与覆盖的'A'值:

d1.values[:, 0] = 2 
d1 

    A B 
0 2 1 

然而,当我做同样的事情与d2,我得到不同的结果,因为它开始了。

d2 

    A B 
0 0 a 

然后:

d2.values[:, 0] = 2 
d2 

    A B 
0 0 a 

什么都没有改变,只是当我这样做:

d2.A.values[:] = 2 
d2 

    A B 
0 2 a 

为什么这种行为不一致?

回答

6

由于d2中混合的dtype s,当您访问整个.values时,您会收到一个object数组(副本)。

>>> d2.values 
array([[0, 'a']], dtype=object) 

这发生在任何不相同的数据类型上,例如,也为int32int64

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

的变化仅传播回来,如果在D型是所有列如出一辙:

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

只给一个(近似)的方式找到如果它是一个视图或您可以使用的实际列的副本np.shares_memory

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

>>> np.shares_memory(d2.values, d2.A.values) 
False 
+2

是的,熊猫通常将它们保持在单独的块中(int在它自己的数组中,而在它自己的数组中),但是当您调用values属性时,它会在混合dtypes时创建一个numpy数组(副本)。 – ayhan

+0

我对内部并不是很熟悉,但是大熊猫可能会将数据帧存储为ND数组,以防万一所有的dtypes都相同(否则它只会将列保留为1D数组)?这将解释它可以如何返回一个视图。 – MSeifert

+1

它有一个名为[BlockManager](http://www.jeffreytratner.com/slides/pandas-under-the-hood-pydata-seattle-2015.pdf)(第36-39页),负责安排不同的dtypes。每个模块在引擎盖下都有自己的numpy数组。因此,例如'd2.A.values [:]'pir直接访问保存int64值的numpy数组。这与'd1.values [:, 0]'是一样的,因为这也是pandas存储的确切的int64 numpy数组。 – ayhan