使用ColumnTransformer处理泰坦尼克数据集时列重复问题排查与解决
问题原因分析
出现列重复的核心原因是ColumnTransformer的拼接逻辑与自定义转换器的输出范围不匹配:
- ColumnTransformer默认会按顺序拼接每个转换器的处理结果,且默认
remainder='passthrough'会把未被任何转换器指定的原始列直接追加到结果中。 - 你的
TransformData类如果在fit_transform时返回的是包含原始列+衍生/处理后列的完整数据集,后续标准化、独热编码又对原始列重新处理,拼接后自然会出现重复列。 - 另外,如果
TransformData处理的列与后续数值/类别转换器的列有重叠,也会导致同一列被多次处理后重复出现。
解决方法
1. 修改自定义TransformData类,仅输出需要的新列
让TransformData只返回衍生、缺失值填充后的目标列,不保留原始输入列。示例如下:
import pandas as pd from sklearn.base import BaseEstimator, TransformerMixin class TransformData(BaseEstimator, TransformerMixin): def fit(self, X, y=None): # 拟合阶段计算缺失值填充的统计量 self.age_median = X['Age'].median() return self def transform(self, X): X_copy = X.copy() # 特征衍生:从Name提取头衔 X_copy['Title'] = X_copy['Name'].str.extract(' ([A-Za-z]+)\.', expand=False) # 缺失值填充 X_copy['Age'] = X_copy['Age'].fillna(self.age_median) # 删除冗余原始列 X_copy = X_copy.drop(['Name', 'Ticket'], axis=1) # 仅返回后续无需重复处理的列 return X_copy[['Title', 'Age']]
2. 明确划分ColumnTransformer的列分组,避免重叠
将数据集列分为三类,确保各组无重叠,同时设置remainder='drop'丢弃未处理的冗余列:
from sklearn.compose import ColumnTransformer from sklearn.preprocessing import StandardScaler, OneHotEncoder # 定义不重叠的列分组 transform_cols = ['Name', 'Age'] num_cols = ['Fare', 'SibSp', 'Parch'] cat_cols = ['Sex', 'Embarked', 'Pclass'] # 构建ColumnTransformer preprocessor = ColumnTransformer( transformers=[ ('custom', TransformData(), transform_cols), ('num', StandardScaler(), num_cols), ('cat', OneHotEncoder(sparse_output=False, drop='first'), cat_cols) ], remainder='drop' # 丢弃未被处理的列,避免残留原始列导致重复 ) # 测试转换 import seaborn as sns titanic = sns.load_dataset('titanic') X = titanic.drop('survived', axis=1) processed_X = preprocessor.fit_transform(X) # 转换为DataFrame查看结果(可选) processed_df = pd.DataFrame(processed_X, columns=preprocessor.get_feature_names_out()) print(processed_df.columns)
3. 替代方案:用Pipeline将TransformData作为前置步骤
如果不想修改自定义类的输出,可以先执行TransformData完成初始清洗,再用ColumnTransformer处理后续列:
from sklearn.pipeline import Pipeline full_pipeline = Pipeline([ ('custom_transform', TransformData()), ('preprocess', ColumnTransformer( transformers=[ ('num', StandardScaler(), ['Fare', 'SibSp', 'Parch', 'Age']), ('cat', OneHotEncoder(sparse_output=False, drop='first'), ['Sex', 'Embarked', 'Pclass', 'Title']) ], remainder='drop' )) ]) processed_X = full_pipeline.fit_transform(X)
这种方式下,第一步已经完成特征衍生、缺失值填充和冗余列删除,后续ColumnTransformer仅处理清洗后的列,不会引入重复。
内容的提问来源于stack exchange,提问作者maolmedilla
相关产品推荐
相关产品推荐

