You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

sklearn的Pipeline搭配ColumnTransformer时OneHotEncoder无法正常运行报错

问题根因

核心错误是ColumnTransformer输出列顺序变化导致的索引错位,具体逻辑如下:

  • 原始数据集的列索引对应关系为:0:kms_driven(数值)、1:owner(字符串)、2:location(字符串)、3:mileage(数值)、4:power(数值)、5:brand(字符串)、6:engine(数值)、7:age(数值)
  • 第一步的imputer_transformer仅对[0,3,4,6,7]5个数值列做缺失值填充,剩余的owner、location、brand3个字符串列通过remainder='passthrough'放在输出结果的末尾,因此第一步输出的列顺序变为:[kms_driven, mileage, power, engine, age, owner, location, brand]
  • 第二步的category_transformer仍然使用原始数据集的列索引做处理,原本要做独热编码的location、brand对应新索引为6、7,不在你指定的[2,5]范围内,这两个未处理的字符串列直接透传到后续线性回归模型,触发字符串转数值的报错。

补充:KNNImputer仅支持数值型输入,你当前的写法刚好只把数值列传给KNNImputer所以没在这一步报错,但如果后续字符串列有缺失值也无法通过这个步骤处理。

最优解决方案

不要拆分两个ColumnTransformer,直接按特征类型分组,所有预处理逻辑放到同一个ColumnTransformer中,避免列顺序变化导致的索引错位问题,同时逻辑更清晰。

修正后代码示例

import numpy as np
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder, MinMaxScaler
from sklearn.compose import ColumnTransformer
from sklearn.impute import KNNImputer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LinearRegression

# 按特征类型分组,直接用列名匹配(适配pandas DataFrame输入,不会出现索引错位)
numeric_cols = ['kms_driven', 'mileage', 'power', 'engine', 'age']
ordinal_col = ['owner']
nominal_cols = ['location', 'brand']

# 数值特征处理:缺失值填充+归一化
numeric_transformer = Pipeline([
    ('knn_imputer', KNNImputer(n_neighbors=5)),
    ('min_max_scaler', MinMaxScaler())
])

# 有序分类特征处理:序数编码
ordinal_transformer = OrdinalEncoder(
    categories=[['fourth','third','second','first']],
    handle_unknown='ignore',
    dtype=np.int16
)

# 无序分类特征处理:独热编码
nominal_transformer = OneHotEncoder(
    sparse_output=False, # sklearn 1.2以下版本用sparse=False
    handle_unknown='ignore'
)

# 整合所有预处理逻辑
preprocessor = ColumnTransformer([
    ('numeric', numeric_transformer, numeric_cols),
    ('ordinal', ordinal_transformer, ordinal_col),
    ('nominal', nominal_transformer, nominal_cols)
])

# 构建完整管道
def build_pipeline_with_estimator(estimator):
    return Pipeline([
        ('preprocessor', preprocessor),
        ('estimator', estimator)
    ])

# 调用测试
linear_regressor = build_pipeline_with_estimator(LinearRegression())
linear_regressor.fit(X_train, y_train)

其他可选方案

如果你坚持要用列索引匹配,需要把第二步category_transformer的索引修改为第一步输出后的对应索引,该方案不推荐,索引维护成本极高,很容易再次出现错位问题:

category_transformer = ColumnTransformer([
    ("kms_driven_engine_min_max_scaler",MinMaxScaler(),[0,3]), # 对应第一步输出的kms_driven、engine
    ("owner_ordinal_enc",OrdinalEncoder(categories=[['fourth','third','second','first']],handle_unknown='ignore',dtype=np.int16),[5]), # 对应第一步输出的owner
    ("brand_location_ohe",OneHotEncoder(sparse=False,handle_unknown='ignore'),[6,7]), # 对应第一步输出的location、brand
],remainder='passthrough')

内容的提问来源于stack exchange,提问作者Ropali Munshi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 22:09:03