在 Pandas 数据框列的子集上的管道中使用 scikit StandardScaler

Posted

技术标签:

【中文标题】在 Pandas 数据框列的子集上的管道中使用 scikit StandardScaler【英文标题】:Using scikit StandardScaler in Pipeline on a subset of Pandas dataframe columns 【发布时间】:2018-10-23 02:56:05 【问题描述】:

我想在 pandas 数据框列的子集上使用 sklearn.preprocessing.StandardScaler。在管道之外,这是微不足道的:

df[['A', 'B']] = scaler.fit_transform(df[['A', 'B']])

但现在假设我在 df 中具有字符串类型的列“C”和以下管道定义

from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline

pipeline =  Pipeline([
                ('standard', StandardScaler())
            ])

df_scaled = pipeline.fit_transform(df)

如何告诉 StandardScaler 仅缩放 A 列和 B 列?

我习惯了 SparkML 管道,可以将要缩放的特征传递给缩放器组件的构造函数:

normalizer = Normalizer(inputCol="features", outputCol="features_norm", p=1.0)

注意:特征列包含一个稀疏向量,其中包含由 Spark 的 VectorAssembler 创建的所有数字特征列

【问题讨论】:

【参考方案1】:

在直接 sklearn 中,您需要将 FunctionTransformerFeatureUnion 一起使用。也就是说,您的管道将如下所示:

pipeline =  Pipeline([
            ('scale_sum', feature_union(...))
        ])

在特征联合中,一个函数会将标准缩放器应用于某些列,而另一个函数将通过其他列保持不变。


使用Ibex(我合写的正是为了让 sklearn 和 pandas 更好地工作),你可以这样写:

from ibex.sklearn.preprocessing import StandardScaler
from ibex import trans

pipeline = (trans(StandardScaler(), in_cols=['A', 'B']) + trans(None, ['c', 'd'])) | <other pipeline steps>

【讨论】:

我可以确认单阶段 IBEX 可以按设计工作并保留未触及的列,但是当连接阶段时它不起作用,您能看看以下问题吗? ***.com/questions/50329184/… @RomeoKienzler 谢谢,我在那里回答了你的问题。【参考方案2】:

您可以查看sklearn-pandas,它提供了 Pandas DataFrame 和 sklearn 的集成,例如使用 DataFrameMapper:

mapper = DataFrameMapper([
...     (list_of_columnnames, StandardScaler())
... ])

如果你不需要外部依赖,你可以使用一个简单的自己的转换器,正如我回答的here:

class Columns(BaseEstimator, TransformerMixin):
    def __init__(self, names=None):
        self.names = names

    def fit(self, X, y=None, **fit_params):
        return self

    def transform(self, X):
        return X[self.names]

pipe =  make_pipeline(Columns(names=list_of_columnnames),StandardScaler())

【讨论】:

我真的很难决定最终接受哪个答案。我选择了@ami Tavory 的答案,因为使用 ibex 时,语义完全符合需要(我可以指定要应用转换器的列以及在管道元素级别返回的列 很公平:)。最后,这都是可行的答案和品味问题/或我猜的具体情况! @MarcusV。标准缩放数据后,已发送到StandardScaler 的列将返回到管道中的下一步。如何只将一些列发送到StandardScaler,但下一步,发送剩余的列和缩放的列。 DataFrameMapper 可以使用参数default 设置为None,那么它们将被转发而不进行转换。对于管道,您还可以使用sklearn.compose.ColumnTransformer 或编写您自己的简单转换器,如上所示,只需在transform 中编写return X

以上是关于在 Pandas 数据框列的子集上的管道中使用 scikit StandardScaler的主要内容,如果未能解决你的问题,请参考以下文章

Python pandas,使用 .str.contains 搜索数据框列的子字符串时出错

来自 pandas 数据框列的 dict

基于针对另一列的参考表更新 Pandas 数据框列的问题

根据数据类型获取 pandas 数据框列的列表

Python pandas 通过对现有列进行分组来创建其他数据框列

熊猫数据框列的分组和计数