我有一个带有强制数据类型的DataFrame,这对我的应用程序非常重要:
df = (pd.DataFrame([(1, 1, 1000),
(1, 2, 2000)],
columns=['id', 'fk', 'value'])
.astype({'id': pd.Int32Dtype(),
'fk': pd.Int32Dtype(),
'value': pd.Float32Dtype()})
df.dtypes.to_dict()
正确的收益率:
{'id': Int32Dtype(), 'fk': Int32Dtype(), 'value': Float32Dtype()}
然而,当我使用.iloc
选择一行时,Pandas突然将所有内容强制转换为float——可能是因为它将其转换为一个需要数据类型的系列:
df.iloc[0].dtypes
收益率:
Float64Dtype()
这会导致下游问题,因为我需要正确类型的数据。如何在保持正确类型的同时拉出一行?
您想要从DataFrame
:中提取Series
(一行(
>>> df
id fk value
0 1 1 1000.0 # Int32, Int32, Float32
1 1 2 2000.0
>>> df.iloc[0]
id 1.0
fk 1.0
value 1000.0
Name: 0, dtype: Float64
因此,您有2行Int32
和1行Float32
。但是,不能混合Series
(或DataFrame
的列(的数据类型。熊猫必须将你的Series
转换成符合你价值观的通用数据类型。这里是Float64
。
现在是另一种情况:
df = pd.DataFrame([(1, 1, 1000), (1, 2, 2000)], columns=['id', 'fk', 'value'])
.astype({'id': pd.Int8Dtype(), 'fk': pd.Int16Dtype(), 'value': pd.Int32Dtype()})
>>> df.dtypes
id Int8
fk Int16
value Int32
dtype: object
>>> df.iloc[0]
id 1
fk 1
value 1000
Name: 0, dtype: Int32
在这种情况下,Pandas会找到一个通用的dtype(超集(来封装值。
根据@MichaelSzczesny和@Corralien的评论(谢谢!(,我知道不可能有多个类型的Series,但一行的DataFrame(例如df.iloc[[0]]
(保留了数据类型。
我现在已经使用它将数据提取到dict
中,保留基本数据类型(int
、float
等(,这对于我的用例来说已经足够好了:
df.iloc[[0]].to_dict('records')[0]
收益率:
{'id': 1, 'fk': 1, 'value': 1000.0}