Pandas链式调用sklearn OrdinalEncoder后astype('int8')不生效问题
问题成因
这个问题是Pandas 1.2.3版本的批量赋值类型逻辑和sklearn输出格式的兼容性导致的,具体可拆解为以下两点:
- 类型转换中间态触发自动向上转型
OrdinalEncoder的fit_transform方法默认返回float64类型的numpy数组,就算你链式调用了.astype('int8')得到了int8类型的numpy数组,在赋值给原有DataFrame列的时候,由于原始df的三个列类型分别是object、object、int64,旧版本Pandas处理多列跨类型批量赋值时,会默认触发类型向上兼容逻辑,为了匹配原有列的类型兼容性,自动把int8类型提升为int64。 - 重复执行生效的原因
第一次链式调用执行完成后,三个列的类型已经全部被转为int64,属于统一的数值类型。第二次执行赋值时,不再存在跨类型兼容的场景,Pandas就会保留右值的int8类型,所以第二次执行可以得到预期结果。
单独调用astype('int8')可以生效的原因也和上面的逻辑一致:单独调用时,目标列已经是统一的数值类型,不需要做跨类型兼容处理,所以可以正确转换类型。
解决方案
你可以任选以下方法解决这个问题:
- 把编码后的结果先转成DataFrame再赋值,让Pandas按列匹配保留类型:
df[bin_cols] = pd.DataFrame( OrdinalEncoder().fit_transform(df[bin_cols]), columns=bin_cols ).astype('int8')
- 链式赋值完成后,额外加一行类型转换代码:
df[bin_cols] = df[bin_cols].astype('int8')
- 升级Pandas到1.3.0及以上版本,该版本已经修复了这个批量赋值的类型自动提升bug。
内容的提问来源于stack exchange,提问作者haneulkim
相关产品推荐
相关产品推荐

