为啥 Pandas 将我的 numpy float32 强制转换为 float64?
Posted
技术标签:
【中文标题】为啥 Pandas 将我的 numpy float32 强制转换为 float64?【英文标题】:Why does Pandas coerce my numpy float32 to float64?为什么 Pandas 将我的 numpy float32 强制转换为 float64? 【发布时间】:2016-05-15 19:09:47 【问题描述】:为什么 Pandas 在这段代码中将我的 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 尝试过这段代码。
这是一个错误还是我误解了 Pandas 中的某些“功能”?如果它是一个功能,那么我该如何绕过它?
(强制问题与我最近询问的关于 Pandas 作业性能的问题有关:Assignment of Pandas DataFrame with float32 and float64 slow)
【问题讨论】:
可能有点奇怪,但和numpy一致。 Numpy 自动将偶数整数转换为 numpy.float64 类型。由于 Pandas 以 numpy 为核心,因此 IMO 需要此功能(尽管在您的情况下肯定不理想)。 但是'pandas' 比普通的numpy
更倾向于使用'dtype=object'。它在处理混合类型时提供了更大的灵活性 - 字符串可以是任意长度,列可以混合类型等。但灵活性伴随着计算和内存成本。
【参考方案1】:
我认为值得将此作为 GitHub 问题发布。行为肯定不一致。
代码根据 DataFrame 是否为混合类型(source)采用不同的分支。
在混合类型的情况下,ndarray 被转换为 float64 数字的 Python 列表,然后在不考虑 DataFrame 的 dtypes 信息的情况下转换回 float64 ndarray (function maybe_convert_objects())。
在非混合类型的情况下,DataFrame 内容几乎直接更新 (source),DataFrame 保持其 float32 dtypes。
【讨论】:
【参考方案2】:不是答案,而是我对这个问题的再现:
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'
我对@987654322@ 不像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)
【讨论】:
单列赋值和列名上的for循环似乎为“类型内”(非强制转换)赋值提供了合理的性能,并产生了正确的类型。但是,如果在 float32 和 float64 之间进行转换,则该方法的速度会慢两倍以上。我想多次重新分配可以解释后一个问题。以上是关于为啥 Pandas 将我的 numpy float32 强制转换为 float64?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 32 位和 64 位 numpy/pandas 之间存在差异
为啥 numpy 函数在 pandas 系列/数据帧上这么慢?