为何向DataFrame赋值np.nan会导致列数据类型从int转为float?
问题:DataFrame赋值np.nan后列类型从int32变为float64的原因?
先看复现代码:
import pandas as pd import numpy as np np.random.seed(1) # Python 2.7.12 # pandas和numpy均为最新版本 print pd.__version__ # 0.23.0 print np.__version__ # 1.14.3 arr = np.random.randint(1, 16, 10).reshape(2, 5) print arr """ [[ 6 12 13 9 10] [12 6 1 1 2]] """ df = pd.DataFrame(arr) print df print 'df[4].dtypes = {}'.format(df[4].dtypes) """ 0 1 2 3 4 0 6 12 13 9 10 1 12 6 1 1 2 df[4].dtypes = int32 """ df.iloc[1, 4] = np.nan print 'df[4].dtypes = {}'.format(df[4].dtypes) # df[4].dtypes = float64
向DataFrame的指定位置赋值np.nan后,对应列的数据类型从int32变为了float64,这背后的原因其实很好理解:
核心原因:整数类型无法兼容缺失值
np.nan本身是浮点类型:你可以自己测试下,type(np.nan)返回的是<type 'float'>,它本质是一个特殊的浮点数。- numpy数组的类型一致性要求:pandas的DataFrame列底层依赖numpy数组,而numpy数组的规则是所有元素必须是同一种数据类型。当你往全是整数的列里插入一个浮点类型的
np.nan时,整个列的类型必须升级到能同时容纳整数和np.nan的类型。 - 为什么是float64?:整数类型没有办法表示缺失值(总不能用某个特殊整数代替,那样会和真实业务数据混淆),而浮点类型天然支持
nan这个特殊值。另外pandas默认选择精度更高的float64,也是为了尽可能减少数据精度损失。
简单类比下:就像你有个只能装苹果的篮子,现在要放个橙子进去,只能把篮子换成能装两种水果的容器——这里的“篮子”就是列的数据类型,np.nan是橙子,float64就是兼容两者的新容器。
如果之后你想保留缺失值同时转回整数类型,可以用pandas的可空整数类型:df[4] = df[4].astype('Int32')(注意是大写的Int32,这是pandas专门为带缺失值的整数场景设计的类型)。
内容的提问来源于stack exchange,提问作者IMCoins
相关产品推荐
相关产品推荐

