ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

scikit-learn ColumnTransformer:数据预处理列变换器实战指南

scikit-learn ColumnTransformer:数据预处理列变换器实战指南 机器学习项目里数据预处理是特别容易写出“面条代码”的环节。数值列要归一化类别列要 one-hot缺失值要按列分别处理处理完还得保证训练集和测试集走完全相同的逻辑。很多人一开始直接在 pandas 里手动挑列、切片、合并代码越写越长最后在交叉验证或线上推理时莫名崩掉。这次我们看一个专门解决这类问题的 sklearn 组件ColumnTransformer列变换器。它解决的核心问题非常具体——在一份数据集里对不同列执行不同的预处理规则。遇到数值列走标准化类别列走独热编码还可以把不想管的列直接透传全程不需要手写切片、拼接的逻辑也不必再担心训练集和测试集处理不一致。本文会从环境准备开始带你完成 ColumnTransformer 的安装验证、基础使用、与 Pipeline 整合、交叉验证和网格搜索实战最后给出一份常见报错排查清单不管是课程作业还是实际项目都能直接参考。1. 核心能力速览先说关键信息。ColumnTransformer 不是一个新的算法模型它是 scikit-learn 在经典 preprocessing 模块之上提供的一个“列路由”组件本身没有独立的拟合逻辑而是管理和调度你传入的多个子变换器。能力项说明组件类型scikit-learn 数据预处理组合器核心功能对不同列应用不同变换器支持按列名、列索引或布尔掩码选择列依赖库scikit-learn、numpy、pandas主要入口from sklearn.compose import ColumnTransformer与 Pipeline 配合支持作为 Pipeline 第一步后续接模型或做网格搜索剩余列控制remainder参数支持丢弃、透传或指定变换器处理剩余列输出格式默认 numpy 数组或稀疏矩阵支持切换为 pandas DataFrame支持批量任务不直接提供批量接口但可通过fit、transform封装后对任意规模新数据重复调用是否支持 API无网络服务 API它是一个 Python 库组件以拟合器和转换器形式提供接口适用人群机器学习初学者、接数据清洗任务的算法工程师、需要结构化预处理代码的团队这套设计带来的直接收益有三个第一代码结构清晰每一类列的预处理方式都在同一个配置里第二训练和推理读写一致不会出现测试集上漏掉某个填充步骤第三配合 Pipeline 可以直接做交叉验证和网格搜索预处理参数也能一起调。2. 适用场景与使用边界ColumnTransformer 适合的场景很明确一份表格型数据里同时存在不同语义的列并且这些列需要不同的预处理方式。典型情况就是“数值列 类别列”混合的数据集。比如年龄、收入用标准化城市、职业用独热编码这种需求在业务风控、营销预测、电商推荐的特征工程里到处可见。它还特别适合数据集里存在“需要特殊处理但又不方便单独建模”的列。比如一个时间戳列你可以传一个函数式变换器先做特征抽取比如一个长文本列你可以先接 TF-IDF 向量化再和其他结构化特征拼在一起。ColumnTransformer 允许一个 DataFrame 同时走多条完全不同的预处理链路。不过也要说清楚它的边界它适合“行数较多、列数中等”的常规表格数据。如果特征是超高维稀疏数据通常直接走专用工具比如文本分类直接用 TF-IDF 管道不一定需要 ColumnTransformer。它本身不做特征选择、不做降维、不做样本采样那些是其他模块的职责。它解决的是预处理流程组织问题不解决脏数据本身的问题。列名不一致、数据分布漂移、标签噪声这些仍然要单独处理。它在单机内存中运行数据量如果大到需要分布式计算需要考虑换 Spark 等方案而不是在 ColumnTransformer 里强行装下全部数据。从合规角度也需要提醒一句如果数据里包含个人信息、人脸信息、声音或其他敏感字段在进入预处理流程前就要做好脱敏和访问控制不要用真实敏感数据随便跑公开的课程测试。本文所有示例使用虚构的结构化数据仅用于演示 API 行为。3. 环境准备与前置条件在写代码之前先确认环境里有一份能正常工作的 scikit-learn。ColumnTransformer 从 scikit-learn 0.20 版本开始正式提供建议使用较新的稳定版本至少不低于 1.0因为旧版本在get_feature_names_out、set_output等接口上有明显差距很多新写法的效果会不一样。推荐环境如下操作系统Windows / Linux / macOS 均可。Python 版本3.8 或更高。scikit-learn1.0 以上推荐 1.2 或更高。其他依赖numpy、pandas。运行方式Jupyter Notebook 或普通 Python 脚本都可以。如果你电脑里还没有 scikit-learn直接使用 pip 安装pip install scikit-learn pandas numpy安装完成后建议先跑一个版本确认命令确保当前环境里能正常导入相关模块。import sklearn from sklearn.compose import ColumnTransformer from sklearn.preprocessing import StandardScaler, OneHotEncoder print(scikit-learn version:, sklearn.__version__) print(ColumnTransformer imported:, ColumnTransformer)如果import sklearn这一步报错说明 scikit-learn 没有安装成功。如果在 jupyter 里出现ModuleNotFoundError: No module named sklearn通常是当前内核对应的 Python 环境不对可以检查sys.executable确认 pip 装到的环境和当前内核一致。import sys print(sys.executable)如果输出路径和实际用的 Python 不一致建议在命令行用当前 Python 重新安装依赖或者切换 kernel。这个步骤虽然简单但实际遇到问题最多的就是环境错乱。4. 项目引入与快速上手ColumnTransformer 不是独立服务所以部署方式就是“在项目中引入”。下面的例子演示最经典的使用方式一份混合数值列和类别列的 DataFrame先定义两组独立预处理流程再组合到一个 ColumnTransformer 中。4.1 构造示例数据import pandas as pd df pd.DataFrame({ age: [25, 30, 28, None, 40], salary: [50000, None, 55000, 60000, 52000], city: [Beijing, Shanghai, Beijing, Guangzhou, Shanghai], position: [ML Engineer, Data Analyst, ML Engineer, DE, DE], })这里故意在 age 和 salary 里制造了缺失值方便演示填充逻辑city 和 position 是类别列。4.2 定义数值列和类别列各自的流水线数值列的常见做法是“先填充缺失值再标准化”这一步要放到一个小型 Pipeline 里面。类别列的常见做法是“先填充缺失值再独热编码”同样放在 Pipeline 里。from sklearn.pipeline import Pipeline from sklearn.impute import SimpleImputer from sklearn.preprocessing import StandardScaler, OneHotEncoder numeric_features [age, salary] categorical_features [city, position] numeric_transformer Pipeline(steps[ (imputer, SimpleImputer(strategymedian)), (scaler, StandardScaler()), ]) categorical_transformer Pipeline(steps[ (imputer, SimpleImputer(strategymost_frequent)), (onehot, OneHotEncoder(handle_unknownignore)), ])这里的handle_unknownignore对于类别列很重要。训练时如果类别数量有限等到实际推理时出现了没见过的类别不会直接报错而是该维度全为 0这种容错在真实场景里非常实用。4.3 组合成 ColumnTransformerfrom sklearn.compose import ColumnTransformer preprocessor ColumnTransformer( transformers[ (num, numeric_transformer, numeric_features), (cat, categorical_transformer, categorical_features), ] )这个 preprocessor 本身就像是一个普通的 sklearn 转换器可以调用fit、transform也可以直接放进 Pipeline 里。4.4 执行转换并查看结果X_transformed preprocessor.fit_transform(df) print(输出维度:, X_transformed.shape) print(X_transformed)输出维度由三部分组成两个数值列标准化后的 2 列类别列独热编码后的若干列。实际列数取决于 city 和 position 的类别数量。从这个例子可以看到ColumnTransformer 已经把“按列路由”这件事完全接管了不用再做df[cols].copy()之类的切片和合并操作。5. 功能测试与效果验证上手之后下一步要做系统性的功能验证。下面提到的几个测试点建议逐个跑一遍不仅帮你理解 API也能在后续实际项目中快速定位问题。5.1 基础测试混合类型列处理是否正确测试目的确认数值列和类别列各自走了对应的变换器。操作步骤使用 4.1 的示例数据调用fit_transform后检查输出矩阵的列数和内容。预期结果age 列的缺失值被中位数填充然后完成标准化。salary 列同理。city 和 position 列先填充缺失值再做 one-hot 编码。最终输出是一个二维数组或矩阵。判断成功的标准输出形状为“样本数 × (2 类别编码列数)”并且观察数值列均值为 0、方差为 1 的量级。不需要手动算所有值但至少确认列数变化符合预期。常见失败原因如果transformers列表里的列名写错会报类似ValueError: A given column is not a column of the dataframe。应检查列名是否和 DataFrame 实际列名完全一致包括中文、空格和大小写。5.2 remainder 参数未被列出的列怎么办默认情况下没有出现在transformers里的列会被直接丢弃。但很多时候你希望一部分列原样保留这时可以用remainder参数。df2 pd.DataFrame({ age: [25, 30, 28], salary: [50000, 60000, 55000], city: [Beijing, Shanghai, Beijing], id: [A001, A002, A003], }) preprocessor ColumnTransformer( transformers[ (num, StandardScaler(), [age, salary]), (cat, OneHotEncoder(), [city]), ], remainderpassthrough ) X2 preprocessor.fit_transform(df2) print(输出维度:, X2.shape)测试要点观察输出矩阵中 id 列是否保留在最后一列。remainderpassthrough会让所有未指定的列在输出中保持原样并默认追加在所有显式变换列的后面。这个顺序对于理解模型特征非常重要尤其是你后面要做特征重要性分析时不能搞混列顺序。另一种写法是给剩余列也指定一个变换器preprocessor ColumnTransformer( transformers[ (num, StandardScaler(), [age, salary]), (cat, OneHotEncoder(), [city]), (id, passthrough, [id]), ], remainderdrop )从可读性来说给每一组列都显式写清楚更推荐比依赖remainderpassthrough隐含行为更不容易出错。5.3 获取输出列名get_feature_names_out转换之后你拿到的可能是一个纯 numpy 数组光看数字无法判断哪一列对应哪个特征。从 scikit-learn 1.0 开始ColumnTransformer 提供了get_feature_names_out方法可以拿到输出特征的名称这是理解转换结果、写模型解释报告的关键能力。feature_names preprocessor.get_feature_names_out() print(feature_names)输出结果会是一组格式化的名称例如[num__age, num__salary, cat__city_Beijing, cat__city_Shanghai, ...]每个名字的前缀对应你在 ColumnTransformer 定义时的变换器名称中间用双下划线分隔后面是原始特征名或类别名。这种命名规则在网格搜索的参数里也会用到所以值得记住。需要说明的是get_feature_names_out必须在fit之后调用因为部分变换器要看到数据之后才知道最终输出哪些列。5.4 与 Pipeline 集成完整建模链路ColumnTransformer 最常见的用法是作为 Pipeline 的第一步后面接一个分类或回归模型。这样预处理和模型训练被封装在同一个对象里交叉验证时不会发生数据泄露推理时也能直接对原始 DataFrame 做预测。from sklearn.linear_model import LogisticRegression from sklearn.model_selection import cross_val_score pipeline Pipeline(steps[ (preprocessor, preprocessor), (classifier, LogisticRegression(max_iter1000)), ]) # 构造一个模拟分类标签 import numpy as np y np.array([0, 1, 0, 1, 1]) scores cross_val_score(pipeline, df, y, cv3, scoringaccuracy) print(交叉验证得分:, scores)这里的关键点是cross_val_score会在每一折内部先对训练部分做fit再对验证部分做transform。不会出现“先用全部数据拟合预处理器再做交叉验证”这种数据泄露问题。这正是把 ColumnTransformer 放进 Pipeline 的最大价值预处理参数比如填充值、标准化均值和方差、one-hot 类别列表都只会从当前训练折中学习。5.5 配合 GridSearchCV 调参ColumnTransformer 内部子变换器的参数也能通过 Pipeline 暴露给GridSearchCV。参数名用双下划线__连接不同层级。from sklearn.model_selection import GridSearchCV param_grid { preprocessor__num__imputer__strategy: [mean, median], classifier__C: [0.1, 1, 10], } grid GridSearchCV(pipeline, param_grid, cv3) grid.fit(df, y) print(最佳参数:, grid.best_params_) print(最佳得分:, grid.best_score_)上面这个例子说明ColumnTransformer 不只是“处理列”它把预处理阶段也变成了可搜索的超参数空间。你在实际项目里可以更进一步把 OneHotEncoder 的handle_unknown行为、SimpleImputer 的填充策略都放进候选列表整体自动化调参。5.6 输出 DataFrame 模式默认情况下 ColumnTransformer 输出 numpy 数组或稀疏矩阵。如果你希望直接得到 pandas DataFrame可以用set_output方法。这是新版 sklearn 提供的统一接口非常实用。preprocessor.set_output(transformpandas) X_df preprocessor.fit_transform(df) print(X_df.head())这时拿到的结果就是一个带列名的 DataFrame列名就是get_feature_names_out的结果后续如果要导出、可视化、做特征筛选会方便很多。需要注意set_output只在较新版本中支持如果报错先升级 sklearn。6. 接口能力与批量转换ColumnTransformer 虽然不像 web 服务那样有 HTTP API但它作为 sklearn 转换器本身的接口设计就够支撑工程化使用。这一节会把核心方法整理成速查表并演示如何对多批新数据做转换以及如何在服务化场景里保存和复用。6.1 核心方法速查方法功能使用场景fit拟合所有子变换器只在训练数据上调用transform应用已拟合的转换逻辑验证集、测试集、推理数据fit_transform先拟合再转换训练数据一步到位get_feature_names_out获取输出特征名理解列顺序、做解释性分析set_params修改内部参数配合网格搜索逐项调参set_output切换输出为 pandas后续处理更直观需要特别强调fit永远只在训练集上执行transform可以在任意新数据上重复执行。如果对测试集或线上新数据重新调用fit_transform会重新计算均值、中位数、类别列表导致严重的数据泄露而且模型的线上表现会变得不可复现。6.2 对多批数据做批量转换实际业务中数据往往按天、按小时分批到达比如今天新增 1000 条、明天新增 2000 条。处理方式就是复用同一个已拟合的 preprocessor。preprocessor.fit(df) # 只在历史训练数据上拟合 def transform_batch(data_df): return preprocessor.transform(data_df) # 模拟新批次数据 new_data_1 pd.DataFrame({ age: [31, 22], salary: [59000, 46000], city: [Shanghai, Beijing], position: [DE, ML Engineer], }) new_data_2 pd.DataFrame({ age: [37, None], salary: [64000, 51000], city: [Guangzhou, Shanghai], position: [Data Analyst, DE], }) result_1 transform_batch(new_data_1) result_2 transform_batch(new_data_2) print(第一批输出:, result_1.shape) print(第二批输出:, result_2.shape)这个模式很适合写成一个独立的preprocess.py模块训练脚本、验证脚本、推理脚本都复用同一个函数避免每个地方各自复制一套处理逻辑。6.3 将预处理器和模型一起序列化保存ColumnTransformer 本身已经把所有列的预处理逻辑固化在一个对象里但更推荐把它和最终的分类器或回归器一起包在 Pipeline 里用 joblib 保存成一个文件。之后在不同机器或不同会话里加载使用所有逻辑保持一致。import joblib pipeline.fit(df, y) joblib.dump(pipeline, pipeline.joblib)在推理阶段加载时直接对原始 DataFrame 调用 predict 即可不需要再关心里面有哪些填充步骤和编码步骤。loaded_pipeline joblib.load(pipeline.joblib) predictions loaded_pipeline.predict(new_data_1) print(predictions)这种方式等价于把整套“预处理 模型”打包成黑盒服务无论是 batch 任务还是单条请求都能稳定使用。6.4 批量调参的工程建议当你的项目进入调参阶段GridSearchCV会跑大量组合。这时候有几个收效明显的建议数据量比较大时先把 ColumnTransformer 放在一个memory参数启用的 Pipeline 里让耗时子变换器的结果被缓存。只有前置数据发生变化或参数变化导致结果变化时才会重新执行。组合搜索范围别一开始就拉大先在默认模型参数下验证预处理设置再逐步放开模型参数否则搜索空间会爆炸。对于大数据集把交叉验证的n_jobs和 Pipeline 的memory配合使用能显著减少重复计算但要注意缓存目录的清理避免代码改动后仍读到旧缓存。from tempfile import mkdtemp cachedir mkdtemp() pipeline Pipeline( steps[ (preprocessor, preprocessor), (classifier, LogisticRegression(max_iter1000)), ], memorycachedir )这样preprocessor的转换结果会被缓存到cachedir。注意缓存目录是临时生成的正式项目应该指定一个稳定路径并在不需要时定期清理。7. 资源占用与性能观察ColumnTransformer 不是一个深度学习模型不存在显存占用但它在内存和 CPU 上仍然值得留意尤其是类别列很多、类别基数很高时。7.1 输出矩阵大小观察资源占用最容易的方式是看转换结果的形状和内存占用。import sys X_transformed preprocessor.fit_transform(df) print(输出形状:, X_transformed.shape) print(占用字节估算:, X_transformed.nbytes)如果 OneHotEncoder 对高基数类别列做独热编码输出维度会随着类别数量线性增长。比如一个城市列有 500 个类别就会增加 500 个特征维度。当数据量大时这会直接推高内存。此时更合理的做法是在 OneHotEncoder 中设置min_frequency或max_categories控制输出列数。下面是一个限制类别数量的写法categorical_transformer Pipeline(steps[ (imputer, SimpleImputer(strategymost_frequent)), (onehot, OneHotEncoder(handle_unknownignore, max_categories20)), ])这样频率最高的类别保留其他低频类别会被聚合到“未知”维度内存占用会明显下降。7.2 稀疏矩阵与密集矩阵当 ColumnTransformer 中的某个子变换器输出稀疏矩阵并且整体输出仍然是稀疏可行的最终结果会默认是稀疏矩阵。这在特征维度很高时能省大量内存但如果你不熟悉稀疏矩阵可能会在后续处理时报错。可以通过sparse_threshold参数控制输出密度阈值。preprocessor ColumnTransformer( transformers[ (num, StandardScaler(), [age, salary]), (cat, OneHotEncoder(), [city, position]), ], sparse_threshold0.3 )sparse_threshold的含义是如果输出矩阵的稀疏程度超过阈值就用稀疏矩阵存储否则用密集数组。如果你希望强制得到 numpy 数组可以把remainder处理得简单或者在后面接一个.toarray()但那样做会失去稀疏矩阵的内存优势。更推荐的做法是保持模型训练过程接受稀疏输入因为大多数 sklearn 模型都能直接处理稀疏矩阵。7.3 每次 transform 的性能观察ColumnTransformer 每次transform的成本取决于内部子变换器的复杂度。数值列的 StandardScaler 很快OneHotEncoder 的耗时会随类别数和样本数上升自定义变换器如果有复杂逻辑会成为瓶颈。建议在功能测试阶段就做一个非常简单的耗时观察import time start time.time() preprocessor.fit_transform(df) print(耗时秒:, round(time.time() - start, 4))不要在没有数据依据的情况下把这个耗时数字当作通用结论。实际耗时和样本量、列数、类别基数强相关。你只需要在自己的数据集上观察到一个基线再对比不同参数下的耗时变化就能判断哪些列是主要瓶颈。7.4 降低内存和加速的策略优先保证数值列和类别列的流程简单、可复用。使用handle_unknownignore避免推理时崩溃。对高基数类别列设置max_categories或min_frequency。大批量数据分批 transform不要一次性把全国一个月的数据都载入内存。用 Pipeline 的 memory 参数缓存耗时中间结果。如果自定义变换器内部有循环优先向量化。8. 常见问题与排查方法ColumnTransformer 在实际使用中报错率不低但大部分错误都可以通过看提示信息快速定位。下面整理一份排查清单。问题现象可能原因排查方式解决方案ValueError: A given column is not a column of the dataframe列名拼写错误或列不存在打印df.columns核对列名修正列名注意空格和大小写KeyError报错传入的是 DataFrame但列名索引不对检查列名类型是否一致统一使用字符串列名或整数索引输出是稀疏矩阵代码后续处理报错默认输出格式为稀疏矩阵print(type(output))查看类型使用.toarray()或调整sparse_thresholdMethod get_feature_names_out is only available when the transformer is fitted未先执行fit检查调用顺序先调用fit_transform或fit训练时正常预测时出现未知类别并报错OneHotEncoder 未设置handle_unknown检查默认参数设置handle_unknownignore网格搜索参数名报错Pipeline 层级和参数名前缀不一致打印pipeline.get_params().keys()使用如preprocessor__num__imputer__strategy的双下划线格式列顺序和预期不符未显式列出全部列使用 remainder 后顺序改变调用get_feature_names_out()查看顺序显式声明每一组列减少隐含行为SimpleImputer无法处理字符串类别对类别列使用了strategymean或median查看报错信息类别列改用strategymost_frequent或constantpandas 版本和 sklearn 接口不兼容sklearn 或 pandas 版本过旧查看版本升级到当前稳定版本自定义变换器只收到了切片后的列但代码尝试使用整个 X对 ColumnTransformer 的列路由机制理解偏差在自定义变换器中打印 X.shape只针对传入的列子集做处理不要使用未被选中的列训练好的 pipeline 在别的机器上加载失败依赖版本不同或 joblib 版本不一致检查目标环境依赖使用相同版本或使用 pickle 替代但注意安全性如果遇到ModuleNotFoundError: No module named sklearn先确认当前 Python 环境是否安装 scikit-learn。如果安装了多个 Python 环境或使用虚拟环境优先激活正确环境。如果 conda 和 pip 混用也可能导致库装到了不同位置。9. 最佳实践与使用建议ColumnTransformer 本身不复杂但要用得好还是要建立一套工程习惯。下面这几点是实际项目中比较值得注意的。9.1 把列名单整理成常量不要在代码里到处写[age, salary]尤其是当列名很多时很容易写错。把列名单集中定义在预处理模块的顶部一方面方便修改另一方面也方便做单元测试。NUMERIC_COLUMNS [age, salary] CATEGORICAL_COLUMNS [city, position]这样 ColumnTransformer 的定义会非常清晰后续添加或删除列时也不会在多个地方改来改去。9.2 每个变换器放在独立 Pipeline 里即使某个列组只有一个预处理步骤也建议写成一个小型 Pipeline。原因很简单后续要加缺失值填充、要加异常值截断、要加自定义变换器时不需要改 ColumnTransformer 的整体结构只要在对应 Pipeline 的 steps 里加一项即可。9.3 严格遵循训练与测试处理一致原则在真实项目里数据泄露是非常隐蔽的错误。最容易犯的问题就是用完整数据集去拟合 ColumnTransformer然后再做交叉验证。这样做表面上看没问题但验证集的信息已经通过均值、中位数和类别列表进入了训练过程最终得分会虚高。所以最佳实践是任何数据转换器的拟合都只能在训练折或训练集上进行ColumnTransformer 一定要放进 Pipeline再交给cross_val_score或GridSearchCV去执行。9.4 保留输出特征名服务模型解释在训练完成后把get_feature_names_out()的结果保存下来这对后续的特征重要性分析、SHAP 解释和排查线上特征异常都非常重要。如果模型上线后输出维度对不上第一件事就是和保存的特征名列表对比。9.5 使用set_output(transformpandas)提高可读性如果你大部分时间都在 Jupyter 里做探索性分析强烈建议让 ColumnTransformer 输出 pandas DataFrame。列名直接可见便于中间结果检查和可视化。正式训练脚本可以继续用默认输出灵活切换即可。9.6 注意隐私合规与使用边界如果数据里包含个人信息、图片、音频或其他敏感内容不要在不安全的环境里反复拷贝和实验。预处理阶段同样要遵循最小化原则能脱敏就先脱敏。对模型输出和最终应用场景要有复核机制避免在未经授权的情况下处理他人数据或用模型结果直接做重要决策。10. 总结与下一步ColumnTransformer 解决的是数据预处理阶段“不同列做不同事”的核心组织问题。看完这篇文章你可以先拿一份混合数值列和类别列的公开数据集按照第 4 节的示例把 ColumnTransformer 跑通然后重点验证两件事第一get_feature_names_out输出的列名是否符合预期第二把 ColumnTransformer 放进 Pipeline 后用cross_val_score是否能正常完成交叉验证。最容易踩的坑集中在两处列名写错导致 ValueError以及在训练集之外误调用fit_transform造成数据泄露。只要把这两个点盯住ColumnTransformer 的上手成本其实很低。进一步的方向可以考虑这几个一是学习如何使用自定义变换器通过FunctionTransformer或继承BaseEstimator、TransformerMixin实现针对性的列处理逻辑二是研究如何同时使用两个 ColumnTransformer 做不同的特征抽取并合并结果这时候可以结合FeatureUnion三是把预处理、模型、解释性分析整体封装成一个可复用的建模模板让每一份新数据进来都能跑同一个标准流程。无论后续走哪条路ColumnTransformer 都是 sklearn 预处理链里值得优先掌握的一环。
返回列表