数据, 术→技巧

Scikit-Learn系统化学习之列变换

钱魏Way · · 193 次浏览
!文章内容如有错误或排版问题,请提交反馈,非常感谢!

ColumnTransformer 是 scikit-learn 中用于对数据的不同列应用不同预处理步骤的工具,特别适用于处理包含混合类型特征(如数值型、分类型、文本型)的数据集。

ColumnTransformer核心功能与使用场景

核心功能

  • 分列处理:对数据集的特定列应用不同的转换器(如标准化、独热编码等)。
  • 灵活组合:将多个转换步骤合并为一个对象,便于在Pipeline中使用。
  • 自动拼接结果:按顺序拼接各转换器的输出,形成最终特征矩阵。

适用场景

  • 数据集包含数值型、分类型、文本型等混合特征。
  • 需对不同类型特征分别预处理(如数值列标准化、分类型列独热编码)。

ColumnTransformer 的使用

基本语法与参数

构造函数

from sklearn.compose import ColumnTransformer

ct = ColumnTransformer(
    transformers=[
        ('name1', transformer1, columns1),
        ('name2', transformer2, columns2),
        ...
    ],
    remainder='drop',   # 处理未指定的列:'drop'(默认)或 'passthrough'
    sparse_threshold=0.3,  # 稀疏矩阵合并阈值(稀疏输出比例 > 该值时返回稀疏矩阵)
    n_jobs=None,        # 并行任务数
    verbose=False       # 是否显示处理日志
)

主要参数

  • transformers:定义转换器的列表,每个元素为元组(name, transformer, columns)。
    • name:转换器名称(字符串)。
    • transformer:转换器对象(如StandardScaler())。
    • columns:指定应用的列(通过列名或索引)。
  • remainder:处理未指定的列。
    • ‘drop’(默认):丢弃未提及的列。
    • ‘passthrough’:保留未提及的列,不做处理。
  • sparse_threshold:控制是否输出稀疏矩阵(默认为3,若结果稀疏性高于该值则返回稀疏矩阵)。

基础使用示例

import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder

# 示例数据
data = pd.DataFrame({
    'age': [30, 40, 50],
    'salary': [70000, 80000, 90000],
    'city': ['NY', 'SF', 'SF'],
    'gender': ['M', 'F', 'M']
})

# 定义列转换器
preprocessor = ColumnTransformer(
    transformers=[
        ('num', StandardScaler(), ['age', 'salary']),
        ('cat', OneHotEncoder(), ['city', 'gender'])
    ],
    remainder='passthrough'
)

# 应用转换
X_processed = preprocessor.fit_transform(data)
print(X_processed)

进阶用法

结合 Pipeline 处理缺失值

from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer

# 数值列处理:填充缺失值 → 标准化
numeric_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='mean')),
    ('scaler', StandardScaler())
])

# 分类型列处理:填充缺失值 → 独热编码
categorical_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='most_frequent')),
    ('onehot', OneHotEncoder(handle_unknown='ignore'))
])

# 定义 ColumnTransformer
preprocessor = ColumnTransformer(
    transformers=[
        ('num', numeric_transformer, ['age', 'income']),
        ('cat', categorical_transformer, ['gender'])
    ]
)

处理文本特征

from sklearn.feature_extraction.text import TfidfVectorizer

# 假设数据包含文本列 'text'
text_transformer = TfidfVectorizer(max_features=100)
preprocessor = ColumnTransformer(
    transformers=[
        ('text', text_transformer, 'text'),
        ('num', numeric_transformer, ['age', 'income'])
    ]
)

获取转换后的特征名称

# 获取转换后的特征名称
feature_names = preprocessor.get_feature_names_out()
print("特征名称:", feature_names)
# 输出:
# ['num__age', 'num__income', 'cat__gender_F', 'cat__gender_M']

注意事项与最佳实践

  • 缺失值处理:在ColumnTransformer 前或内部使用 SimpleImputer 填充缺失值,避免转换器报错。
  • 类别型变量处理:使用OneHotEncoder 时设置 handle_unknown=’ignore’,防止测试集出现新类别。
  • 特征名称保留:使用get_feature_names_out() 获取转换后特征名,方便调试和解释模型。
  • 稀疏矩阵优化:若转换器生成稀疏矩阵(如OneHotEncoder),设置 sparse_threshold=0.3 平衡内存与效率。
  • 列选择方式:优先使用列名(pandas数据)而非索引,避免列顺序变化导致错误。

实战案例:泰坦尼克数据集预处理

import pandas as pd
from sklearn.datasets import fetch_openml

# 加载数据
titanic = fetch_openml('titanic', version=1)
X = titanic.data[['pclass', 'sex', 'age', 'fare']]
y = titanic.target

# 定义预处理流程
numeric_features = ['age', 'fare']
categorical_features = ['pclass', 'sex']

numeric_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='median')),
    ('scaler', StandardScaler())
])

categorical_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='most_frequent')),
    ('onehot', OneHotEncoder())
])

preprocessor = ColumnTransformer(
    transformers=[
        ('num', numeric_transformer, numeric_features),
        ('cat', categorical_transformer, categorical_features)
    ]
)

# 构建模型
model = Pipeline(steps=[
    ('preprocessor', preprocessor),
    ('classifier', RandomForestClassifier())
])

# 训练与评估
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
model.fit(X_train, y_train)
print("准确率:", model.score(X_test, y_test))

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注