前処理でsklearnの結果がデータフレームで欲しい(sklearn_pandasを使う)

前処理をしている時に、集計などの処理はpandasで事足りますが、標準化などはsklearnを使いたいことがあります。

▼例えばRobustScalerなど esu-ko.hatenablog.com

このときに、sklearnのpreprocessingはDataFrameではなくnumpy.arrayで返してくるため、そのあとも加工をする場合は不便です。(具体的にはカラムなどの情報が失われてしまうため)

そうした、sklearnとdataframeの接続がめんどくさい時にsklearn-pandasを使うと便利です。ただし結構癖がある部分があったので、その辺も含めてまとめました。

使い方

mapperにカラム名と処理の組み合わせのタプルのリストをわたし、sklearn同様、fit_transfromするだけです。

import sklearn_pandas

mapper = sklearn_pandas.DataFrameMapper(
    [
     #カラム名には複数渡せる
     ([カラム名],処理するpreprocessing)
     #カラム-処理の関係はいくつも渡せる
    ],
    default=None,
    df_out = True
)

# データフレームで帰ってくる
mapper.fit_transform(df)

便利なのは、

  1. 処理ごとにsklearnのインスタンスとデータをバラバラに用意して結合が必要ない
  2. default=Noneを渡すことで、処理しないカラムはそのまま返してくれる

というところです。

注意点

注意点は結構あります。

まず、df_out=Trueにしないと普通にarrayで帰ってきてしまいます。意味ないですね。

また、LabelEncoderの場合は、タプルの一つ目はカラム名のstringで大丈夫ですが、StandardScalerを使う場合は、リストとして渡さないとエラーになります。
分けて考えると面倒なので、常にリストとして渡す方が楽かな、、、

最後に、タプルの一つ目にカラム名を複数入れると、col1_col2_..のような新しいカラム名を生成してめんどくさいです。下に書きますが、一つ一つ処理を作った方があとあと使いやすいと思います。

使ってみる

#データの用意
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
import pandas as pd

sk_ir = load_iris()
df = pd.DataFrame(sk_ir['data'],columns=sk_ir['feature_names'])

df['species']= sk_ir['target']

#species以外にstandardscalerしてみる
import sklearn_pandas

#カラム名と処理のタプルリスト
ss = [([n],StandardScaler() ) for n in df.columns[:4]]

#mapper
mapper = sklearn_pandas.DataFrameMapper(
    [
     ([n for n in df.columns[:4]],StandardScaler())
    ],
    default=None,
    df_out = True
)

#処理実行
mapper.fit_transform(df)

こうすることでspeciesはそのまま、それ以外はStandardScalerがかかった状態のデータフレームを手に入れられました。

▼一緒に使える処理はこちら

esu-ko.hatenablog.com

▼そもそもPandasでやる前処理はこちら

esu-ko.hatenablog.com

esu-ko.hatenablog.com