scikit-learn Pipeline中缺失值填充失效报Input X contains NaN错误
问题根因
报错核心是ColumnTransformer的配置逻辑错误:
ColumnTransformer中定义的多个转换器是按列分组并行执行的,转换完成后会把各分支的结果横向拼接输出,并不会按列表顺序串行处理同一列数据。- 你的代码中对同一组
numeric_columns同时绑定了两个并行分支:一个分支做缺失值均值填充,另一个分支直接跑StandardScaler标准化。标准化分支拿到的是未经过填充的原始带NaN数据,自然触发ValueError: Input X contains NaN报错,后续交叉验证得分全为nan也是这个原因导致的。 - 额外存在一个小索引错误:你将第0列pop作为标签y后,剩余特征列的索引是1~19,原代码写的
numeric_columns = np.arange(19)会取0~18,匹配不到正确的列范围。
修复方案
对同一组数值列的多步处理(填充→标准化),需要嵌套Pipeline实现串行执行,再嵌入到ColumnTransformer中,修正后的完整代码如下:
import numpy as np import pandas as pd from sklearn.impute import SimpleImputer from sklearn.preprocessing import StandardScaler from sklearn.compose import ColumnTransformer from sklearn.cross_decomposition import PLSRegression from sklearn.pipeline import Pipeline from sklearn.model_selection import KFold, GridSearchCV, cross_val_score # 构造模拟数据 X = pd.DataFrame(np.random.rand(20,20)) X.iloc[2,3] = np.nan y = X.pop(0) # 修正列索引:pop第0列后,剩余特征列索引为1~19 numeric_columns = np.arange(1, 20) # 数值列串行处理流:先缺失值填充,再标准化 numeric_transformer = Pipeline(steps=[ ('impute_mean', SimpleImputer(missing_values=np.nan, strategy='mean')), ('scaler', StandardScaler()) ]) feature_transformer = ColumnTransformer( transformers=[ ('num', numeric_transformer, numeric_columns) ], remainder='passthrough' ) # 超参数配置 parameters = {'model__n_components': [1,2,3,4,5]} # 主流水线 pipeline = Pipeline([ ('feature_transformer', feature_transformer), ('model', PLSRegression()) ]) # 交叉验证策略 cv = KFold(n_splits=10, shuffle=True, random_state=42) # 网格搜索+交叉验证评估 clf = GridSearchCV(pipeline, parameters, scoring="r2", cv=cv) score = cross_val_score(clf, X, y, cv=cv, scoring="r2")
额外注意事项
SimpleImputer的fill_value参数仅在strategy='constant'时生效,使用均值填充策略时该参数无效,可删除避免逻辑混淆。- 交叉验证配置中建议添加
random_state参数固定随机种子,保证每次运行结果可复现。 - 编写
ColumnTransformer时要明确:不同列的处理逻辑并行执行,同一列的多步顺序处理必须嵌套Pipeline实现。
内容的提问来源于stack exchange,提问作者RobMcC
相关产品推荐
相关产品推荐

