有没有办法强制变压器返回熊猫数据框?

数据挖掘 scikit-学习 熊猫
2022-02-15 10:17:48

我在 scikit-learn 将数据帧转换为 numpy 数组时遇到问题。

例如下面的代码

from sklearn.impute import SimpleImputer
import pandas as pd

df = pd.DataFrame(dict(
    x=[1, 2, np.nan],
    y=[2, np.nan, 0]
))

SimpleImputer().fit_transform(df)

退货

array([[1. , 2. ],
       [2. , 1. ],
       [1.5, 0. ]])

有没有办法使用返回 pandas 数据框而不是 numpy 数组的 imputer?是否有 scikit-learn 实现?我知道sklearn-pandas,但界面有点不同。

3个回答

可能会迟到,但对于任何有相同问题的人来说,答案(几乎所有 Scikit-learn 的答案)都是使用Pipelines

from sklearn.impute import SimpleImputer
from sklearn.preprocessing import FunctionTransformer
from sklearn.pipeline import Pipeline
import pandas as pd

df = pd.DataFrame(dict(
    x=[1, 2, np.nan],
    y=[2, np.nan, 0]
))

imputer = Pipeline([("imputer", SimpleImputer()),
                    ("pandarizer",FunctionTransformer(lambda x: pd.DataFrame(x, columns = ["x", "y"])))])

imputer.fit_transform(df)

截至 2022 年 4 月 5 日,这在 scikit-learn 中不可用。

好消息是:

希望 scikit-learn 能尽快让处理 pandas 数据帧更加方便。

您可以做的是将您最喜欢的预处理函数重写为新的自定义转换器。这可能需要一些时间来重写,但是当您希望所有内容都作为数据框时,它肯定会很有帮助。例如考虑一个 StandardScaler 的例子:

class DFStandardScaler(TransformerMixin):
    def __init__(self):
        self.ss = None
        self.mean_ = None
        self.scale_ = None
    def fit(self, X, y=None):
        self.ss = StandardScaler()
        self.ss.fit(X)
        self.mean_ = pd.Series(self.ss.mean_, index=X.columns)
        self.scale_ = pd.Series(self.ss.scale_, index=X.columns)
        return self
    def transform(self, X) -> pd.DataFrame:
        # assumes X is a DataFrame
        Xss = self.ss.transform(X)
        Xscaled = pd.DataFrame(Xss, index=X.index, columns=X.columns)
        return Xscaled
    def __str__(self):
         return "DF_StandardScaler"
    def __repr__(self):
         return "DF_StandardScaler"

使用以下 asDFStandardScaler().fit_transform(df)将返回提供的相同数据帧。唯一的问题是这个例子需要一个带有列名的 df,但是从头开始设置列名并不难。

这是 sklearn 关于自定义转换器的文档: https ://scikit-learn.org/stable/modules/preprocessing.html#custom-transformers