2016-02-05 35 views
5

为什么熊猫强迫我numpy的FLOAT32在这一段代码float64:为什么熊猫强迫我的numpy float32 float64?

>>> import pandas as pd 
>>> import numpy as np 
>>> df = pd.DataFrame([[1, 2, 'a'], [3, 4, 'b']], dtype=np.float32) 
>>> A = df.ix[:, 0:1].values 
>>> df.ix[:, 0:1] = A 
>>> df[0].dtype 
dtype('float64') 

行为似乎很奇怪,我不知道这是一个错误。我在Pandas版本0.17.1(已更新的PyPI版本)上,并且我注意到最近解决了一些胁迫错误,请参阅https://github.com/pydata/pandas/issues/11847。我还没有用更新过的GitHub master尝试过这段代码。

这是一个错误还是我误解熊猫的一些“功能”?如果它是一个功能,那么我该如何解决它?

(胁迫问题涉及到一个问题,我最近谈到大熊猫分配的性能:Assignment of Pandas DataFrame with float32 and float64 slow

+0

它可能很奇怪,但它与numpy一致。 Numpy会自动将整数转换为numpy.float64类型。由于Pandas的核心内容是numpy,所以这个功能预计是IMO(尽管在你的情况下肯定不是很理想)。 – Benji

+0

但'大熊猫'更倾向于使用'dtype = object'而不是普通的'numpy'。它在处理混合类型时给予它更大的灵活性 - 字符串可以是任意长度,列可以混合类型等。但灵活性伴随着计算和内存成本。 – hpaulj

回答

1

我认为这是值得张贴这是一个GitHub的问题。这种行为肯定是不一致的。

根据DataFrame是否为混合类型(source),代码将采用不同的分支。

  • 在混合型的情况下ndarray转换为float64号码的Python列表,然后转换回float64 ndarray不顾数据帧的信息dtypes(function maybe_convert_objects())。

  • 在非混合类型的情况下,DataFrame内容几乎直接更新(source),并且DataFrame保持其float32 dtypes。

+0

我构建了一个新问题:https:// github。com/pydata/pandas/issues/12255 –

1

不是一个答案,但我对这个问题的娱乐:

In [2]: df = pd.DataFrame([[1, 2, 'a'], [3, 4, 'b']], dtype=np.float32) 
In [3]: df.dtypes 
Out[3]: 
0 float32 
1 float32 
2  object 
dtype: object 
In [4]: A=df.ix[:,:1].values 
In [5]: A 
Out[5]: 
array([[ 1., 2.], 
     [ 3., 4.]], dtype=float32) 
In [6]: df.ix[:,:1] = A 
In [7]: df.dtypes 
Out[7]: 
0 float64 
1 float64 
2  object 
dtype: object 
In [8]: pd.__version__ 
Out[8]: '0.15.0' 

我不熟悉pandas作为numpy,但我很困惑,为什么ix[:,:1]给了我2列结果。在numpy那种索引只给出1列。

如果我给你一列dtype不会改变

In [47]: df.ix[:,[0]]=A[:,0] 
In [48]: df.dtypes 
Out[48]: 
0 float32 
1 float32 
2  object 

没有混合数据类型相同的动作不会改变dtypes

In [100]: df1 = pd.DataFrame([[1, 2, 1.23], [3, 4, 3.32]], dtype=np.float32) 
In [101]: A1=df1.ix[:,:1].values 
In [102]: df1.ix[:,:1]=A1 
In [103]: df1.dtypes 
Out[103]: 
0 float32 
1 float32 
2 float32 
dtype: object 

的关键必须是混合值,从某种意义上说,数据帧是dtype=object阵列,无论其内部数据存储器是真是假,还是只有它的numpy接口。

In [104]: df1.as_matrix() 
Out[104]: 
array([[ 1.  , 2.  , 1.23000002], 
     [ 3.  , 4.  , 3.31999993]], dtype=float32) 
In [105]: df.as_matrix() 
Out[105]: 
array([[1.0, 2.0, 'a'], 
     [3.0, 4.0, 'b']], dtype=object) 
+0

使用单列和for-loop over列名进行赋值似乎为“内类型”(非赋值)赋值提供了合理的性能,并且会生成正确的类型。但是,如果向float32和float64进行投射,则该方法速度会降低一倍。我想多次重新分配可以解释后一个问题。 –