如何在Python中对分类数据进行空值填充?
Python中分类数据的空值填充方案
嘿,这个问题我太熟了!Python里其实有不少处理分类数据空值的实用办法,不一定非要找和R里DMwR、Caret完全对应的“一站式”库,咱们根据不同场景来选:
1. 基础方案:众数/常数填充
这是最直接的方法,适合快速处理或者缺失值占比不高的情况:
众数填充:用列中出现频率最高的类别填充,pandas和sklearn都能轻松实现:
# 用pandas直接处理单列 data_set['Alley'].fillna(data_set['Alley'].mode()[0], inplace=True) # 用sklearn批量处理所有分类列 from sklearn.impute import SimpleImputer import pandas as pd # 筛选出所有分类列(object或category类型) cat_cols = data_set.select_dtypes(include=['object', 'category']).columns imputer = SimpleImputer(strategy='most_frequent') data_set[cat_cols] = imputer.fit_transform(data_set[cat_cols])注:
mode()[0]是因为pandas的mode()返回的是Series,取第一个元素就是众数。常数填充:如果缺失值本身代表“不存在”这类含义,直接填充一个自定义类别(比如
'Unknown')更合理:data_set['Alley'].fillna('Unknown', inplace=True)
2. 更贴合数据分布:随机频率填充
如果用众数填充会引入偏差(比如某列有多个占比相近的类别),可以按类别出现的概率随机填充:
import numpy as np def random_category_fill(col): # 获取每个类别的频率占比 category_probs = col.value_counts(normalize=True) # 按概率随机选择类别填充空值 return col.fillna(np.random.choice(category_probs.index, p=category_probs.values)) # 应用到目标列 data_set['BsmtCond'] = random_category_fill(data_set['BsmtCond'])
3. 进阶方案:基于机器学习的智能填充
类似R里的KNN或CentralImputation,Python可以通过编码+模型填充的方式实现:
方法A:KNN填充
先把分类列转为数值编码,再用KNNImputer填充,最后转回原类别:
from sklearn.impute import KNNImputer from sklearn.preprocessing import LabelEncoder import pandas as pd cat_cols = data_set.select_dtypes(include=['object', 'category']).columns le_mapping = {} # 先对分类列做标签编码 for col in cat_cols: le = LabelEncoder() # 把空值转成字符串避免编码报错 data_set[col] = le.fit_transform(data_set[col].astype(str)) le_mapping[col] = le # 用KNN填充 imputer = KNNImputer(n_neighbors=5) data_set_imputed = pd.DataFrame(imputer.fit_transform(data_set), columns=data_set.columns) # 转回原类别 for col in cat_cols: data_set_imputed[col] = le_mapping[col].inverse_transform(data_set_imputed[col].astype(int))
方法B:MICE迭代填充(利用其他特征关系)
如果想让填充值更贴合数据的内在关联,可以用迭代填充器,配合分类模型(比如随机森林):
from fancyimpute import IterativeImputer from sklearn.ensemble import RandomForestClassifier from sklearn.preprocessing import LabelEncoder import pandas as pd cat_cols = data_set.select_dtypes(include=['object', 'category']).columns le_mapping = {} # 标签编码分类列 for col in cat_cols: le = LabelEncoder() data_set[col] = le.fit_transform(data_set[col].astype(str)) le_mapping[col] = le # 用随机森林分类器作为迭代填充的基础模型 imputer = IterativeImputer( estimator=RandomForestClassifier(n_estimators=100, random_state=42), max_iter=10, random_state=42 ) data_set_imputed = pd.DataFrame(imputer.fit_transform(data_set), columns=data_set.columns) # 转回原类别 for col in cat_cols: data_set_imputed[col] = le_mapping[col].inverse_transform(data_set_imputed[col].astype(int))
选择建议
- 快速处理/缺失值少:优先选众数或常数填充
- 避免单一类别偏差:用随机频率填充
- 想利用特征间关联:选KNN或MICE迭代填充
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

