onehotencoder默认不支持字符串输入,需确保输入为二维结构、列类型统一、缺失值已处理,并用columntransformer对类别列选择性编码,输出默认为稀疏矩阵。

OneHotEncoder 默认不支持字符串输入,会报 ValueError: Encoders require their input to be uniformly strings or numbers
这是最常遇到的错误。Scikit-learn 1.0+ 版本中,OneHotEncoder 默认要求所有列必须是数值型或统一为字符串类型,不能混用(比如部分是 str、部分是 int),也不能包含 None 或 np.nan。
- 确保传入的是
pandas.DataFrame或二维numpy.ndarray,且目标列 dtype 是object或string(推荐先用df[col].astype("string")显式转换) - 缺失值必须提前处理:用
df.fillna("missing")或df.fillna(df.mode().iloc[0]),不能留NaN - 别直接传
Series——OneHotEncoder要求二维输入,所以得用df[["col_name"]],不是df["col_name"]
用 ColumnTransformer 对混合类型数据做选择性编码
实际数据里往往既有类别列(如 "city", "gender"),又有数值列(如 "age", "income")。硬把全部列喂给 OneHotEncoder 会出错,也浪费资源。
- 只对明确的类别列使用
OneHotEncoder,其他列用"passthrough"或StandardScaler - 注意
ColumnTransformer的remainder参数:设为"drop"会丢弃未指定列;设为"passthrough"则保留原样(但需确保它们是数值型) - 示例片段:
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder
ct = ColumnTransformer(
transformers=[("ohe", OneHotEncoder(drop="if_binary"), ["gender", "country"])],
remainder="passthrough"
)
X_transformed = ct.fit_transform(X)
这里 drop="if_binary" 对二元变量自动只保留一列,避免共线性;若想保留全量 dummy 变量,改成 drop=None 即可。
OneHotEncoder 输出是稀疏矩阵,toarray() 会吃内存
默认输出是 scipy.sparse matrix(通常是 csr_matrix),这对训练树模型或线性模型没问题,但如果你后续要转成 pandas.DataFrame、做切片、或用某些可视化库,就得转稠密数组 —— 这时候 .toarray() 可能爆内存。
- 检查维度:
X_ohe.shape如果第二维(列数)上万,尤其原始类别多、样本少时,稀疏性很重要 - 不想转稠密?可以用
pandas.get_dummies()替代,它默认输出DataFrame,且支持sparse=True(返回稀疏Series) - 如果非得用
OneHotEncoder+ 稠密输出,初始化时加参数sparse_output=False(scikit-learn ≥ 1.2)
新旧版本差异:handle_unknown 和 categories_ 行为变化
训练时没见过的类别,在预测阶段怎么处理?老版本(handle_unknown="ignore" 才跳过,且此时对应列全为 0。
- 设了
handle_unknown="ignore"后,transform()不再报错,但要注意:返回结果列数和fit()时一致,新类别不会新增列 -
categories_是拟合后属性,是个列表,每个元素是对应列的唯一值数组(按出现顺序排),不是字典 —— 别误以为能用键查值 - 若需映射回原始标签,建议配合
pd.Categorical或自己存一份label_to_idx映射表
类别变量编码真正麻烦的从来不是“怎么调通”,而是“训练集有 5 个城市,测试集突然冒出第 6 个”——这个边界情况不提前想清楚,上线后模型就静默失效。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











