为什么Pandas整数'dtypes'在Unix和Windows上的行为不一样?



在检查PandasDataFrame中的列dtypes时,我意识到整数列的数据类型是np.int64,但令人惊讶的是,在Unix上这等同于int但在Windows上则不然。 为什么他们的行为不一样? 有没有办法以使用df.dtypes == int比较时结果相同的方式创建数据帧?

下面是一些示例代码来说明。

In [1]: import numpy as np
In [2]: import pandas as pd
In [3]: pd.__version__
Out[3]: '1.0.1'
In [4]: np.__version__
Out[4]: '1.18.1'
In [5]: data = pd.DataFrame({'col_1': range(5), 'col_2': np.linspace(0, 1, 5)})
In [6]: data.dtypes
Out[6]: 
col_1      int64
col_2    float64
dtype: object
In [7]: data.dtypes == float
Out[7]: 
col_1    False
col_2     True
dtype: bool

所有这些都在Windows和Unix上产生相同的结果,但是如果我将dtypes与Windows上的int进行比较,我会得到

In [8]: data.dtypes == int
Out[8]: 
col_1    False
col_2    False
dtype: bool

在 Unix 上我得到

In [8]: data.dtypes == int
Out[8]:
col_1     True
col_2    False
dtype: bool

我尝试指定数据类型。 这适用于 Unix,我可以通过添加dtype=(int, float)来输入数据类型

In [9]: data = pd.DataFrame({'col_1': range(5), 'col_2': np.linspace(0, 1, 5)}, dtype=(int, float))
In [10]: data.dtypes
Out[10]:
col_1      int64
col_2    float64
dtype: object

但在 Windows 上,此代码失败并显示ValueError

In [10]: data = pd.DataFrame({'col_1': range(5), 'col_2': np.linspace(0, 1, 5)}, dtype=(int, float))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-25-284f0f12d3b6> in <module>
----> 1 data = pd.DataFrame({'col_1': range(5), 'col_2': np.linspace(0, 1, 5)}, dtype=(int, float))
~Miniconda3envspandas_testlibsite-packagespandascoreframe.py in __init__(self, data, index, columns, dtype, copy)
423             data = {}
424         if dtype is not None:
--> 425             dtype = self._validate_dtype(dtype)
426
427         if isinstance(data, DataFrame):
~Miniconda3envspandas_testlibsite-packagespandascoregeneric.py in _validate_dtype(self, dtype)
257
258         if dtype is not None:
--> 259             dtype = pandas_dtype(dtype)
260
261             # a compound dtype
~Miniconda3envspandas_testlibsite-packagespandascoredtypescommon.py in pandas_dtype(dtype)
1872     # raise a consistent TypeError if failed
1873     try:
-> 1874         npdtype = np.dtype(dtype)
1875     except SyntaxError:
1876         # np.dtype uses `eval` which can raise SyntaxError
ValueError: mismatch in size of old and new data-descriptor

熊猫。数据帧具有dtype参数。

pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)

您应该能够使用该参数设置特定的数据类型。

对于比较任何类型的整数或浮点数的平台不可知的方法,您可以使用

In [10]: [np.issubdtype(dtype, np.integer) for dtype in data.dtypes]
Out[10]: [True, False]
In [11]: [np.issubdtype(dtype, np.float) for dtype in data.dtypes]
Out[11]: [False, True]

Windows/Unix差异背后的主要问题是,int等同于在Unix上np.int64的熊猫dtype,在Windows上np.int32

此代码说明了行为上的差异:

import numpy as np
import pandas as pd
print(f'numpy version: {np.__version__}')
print(f'pandas version: {pd.__version__}')
data = pd.DataFrame({
'col_i': range(5),
'col_f': np.linspace(0, 1, 5),
})
data['col_i32'] = data.col_i.astype(np.int32)
data['col_i64'] = data.col_i.astype(np.int64)
data['col_f32'] = data.col_i.astype(np.float32)
data['col_f64'] = data.col_i.astype(np.float64)
print(f'ndata.dtypes: n{data.dtypes}')
print(f'ndata.dtypes == int: n{data.dtypes == int}')
print(f'ndata.dtypes == float: n{data.dtypes == float}')

以下是Windows上的结果:

numpy version: 1.18.1
pandas version: 1.0.1
data.dtypes:
col_i        int64
col_f      float64
col_i32      int32
col_i64      int64
col_f32    float32
col_f64    float64
dtype: object
data.dtypes == int:
col_i      False
col_f      False
col_i32     True  # the np.int32 column
col_i64    False
col_f32    False
col_f64    False
dtype: bool
data.dtypes == float:
col_i      False
col_f       True
col_i32    False
col_i64    False
col_f32    False
col_f64     True
dtype: bool

这是Unix上的输出:

numpy version: 1.18.1
pandas version: 1.0.1
data.dtypes:
col_i        int64
col_f      float64
col_i32      int32
col_i64      int64
col_f32    float32
col_f64    float64
dtype: object
data.dtypes == int:
col_i       True  # a np.int64 column
col_f      False
col_i32    False
col_i64     True  # a np.int64 column
col_f32    False
col_f64    False
dtype: bool
data.dtypes == float:
col_i      False
col_f       True
col_i32    False
col_i64    False
col_f32    False
col_f64     True
dtype: bool

请注意,在 Windows 上指定dtype失败的原因是这些类型必须具有相同的内存大小。 pandas 文档指出"只允许使用单个 dtype",但事实显然并非如此,因为以下任何一个都可以在 Windows 和 Unix 上工作。

data = pd.DataFrame({'col_i32': range(5), 'col_f32': np.linspace(0, 1, 5)}, dtype=(np.int32, np.float32))
data = pd.DataFrame({'col_i32': range(5), 'col_f32': np.linspace(0, 1, 5)}, dtype=(np.int64, np.float64))

我认为他们实际上的意思是"只允许单个[数据大小]"。

指定dtype=(int, float)时的错误问题可以追溯到上面说明的主要问题,其中 Windows 将int转换为np.int32float转换为np.float64,而 Unix 改为将int转换为np.int64float转换为np.float64。 Pandas要求它们具有相同的内存大小,这在Unix上有效,但在Windows上则不行。

>>> np.int64 == int
False
>>> np.int32 == int
False
>>> np.int == int
True
>>> np.int == np.int64
False
>>> np.int == np.int32
False

这是意料之中的,我会坚持通过指定 int64 或 int32 来定义您正在使用的 dtype

最新更新