使用Sklearn的SimpleImputer填充缺失值后数值列变为object类型
类型转换原因
SimpleImputer的transform方法默认返回numpy数组,当输入数据集同时包含数值型和字符型列时,numpy为了兼容不同类型的元素,会将整个数组的dtype统一向上转为object,基于该数组生成DataFrame后,所有列的类型自然都会变为object。
就算输入数据只有数值列,若most_frequent策略返回的众数类型和原列类型不匹配,也可能触发类型向上转换。
解决方案
方案1:填充后手动恢复数值列类型
你已经提前筛选出了所有数值列numerical_cols,填充完成后直接对这些列做类型转换即可,代码如下:
# 恢复训练集数值列类型 imputed_X_train_missing[numerical_cols] = imputed_X_train_missing[numerical_cols].apply(pd.to_numeric) # 恢复验证集数值列类型 imputed_X_valid_missing[numerical_cols] = imputed_X_valid_missing[numerical_cols].apply(pd.to_numeric)
该方法改造成本最低,适合临时快速修复问题。
方案2:分类型列分开填充
将数值列和分类列拆分,分别用对应策略填充后再合并,从根源避免混合类型导致的全局类型转换,同时可以给不同类型列配置更合理的填充策略:
from sklearn.impute import SimpleImputer import pandas as pd import numpy as np # 提前拆分数值列和分类列 numerical_cols = [col for col in X_train_missing.columns if X_train_missing[col].dtype in ['int64','float64']] categorical_cols = [col for col in X_train_missing.columns if X_train_missing[col].dtype == 'object'] # 分别初始化不同策略的填充器 num_imputer = SimpleImputer(strategy='median') # 数值列推荐用中位数/均值填充 cat_imputer = SimpleImputer(strategy='most_frequent') # 分别处理两类列 imputed_num_train = pd.DataFrame(num_imputer.fit_transform(X_train_missing[numerical_cols]), columns=numerical_cols) imputed_cat_train = pd.DataFrame(cat_imputer.fit_transform(X_train_missing[categorical_cols]), columns=categorical_cols) imputed_X_train_missing = pd.concat([imputed_num_train, imputed_cat_train], axis=1) # 验证集做相同处理 imputed_num_valid = pd.DataFrame(num_imputer.transform(X_valid_missing[numerical_cols]), columns=numerical_cols) imputed_cat_valid = pd.DataFrame(cat_imputer.transform(X_valid_missing[categorical_cols]), columns=categorical_cols) imputed_X_valid_missing = pd.concat([imputed_num_valid, imputed_cat_valid], axis=1)
方案3:用ColumnTransformer批量处理(官方推荐写法)
scikit-learn的ColumnTransformer支持直接指定不同列的处理逻辑,0.23及以上版本可以通过set_output接口直接返回带正确类型的DataFrame,不需要手动合并:
from sklearn.compose import ColumnTransformer from sklearn.impute import SimpleImputer # 定义不同列的处理流水线 preprocessor = ColumnTransformer( transformers=[ ('num', SimpleImputer(strategy='median'), numerical_cols), ('cat', SimpleImputer(strategy='most_frequent'), categorical_cols) ]) # 配置输出为pandas DataFrame,保留原始列类型 preprocessor.set_output(transform="pandas") # 直接处理生成符合要求的数据集 imputed_X_train_missing = preprocessor.fit_transform(X_train_missing) imputed_X_valid_missing = preprocessor.transform(X_valid_missing)
内容的提问来源于stack exchange,提问作者Paula Marañón
相关产品推荐
相关产品推荐

