LoginSignup
0
0

More than 1 year has passed since last update.

[素人エンジニア]がscikit-learningのEncodingを勉強した

Last updated at Posted at 2021-05-07

Pythonデータ分析認定試験の合格を目指し
公式テキストを元に学習しているが表題の部分で詰まった

この記事でやってること
・データフレームをOneHotEncodingしたよ
・上記のエンコード済のデータをデータフレーム型に戻してカラム名を表記したよ

環境
python : 3.9.4
scikit-learn : 0.24.2
numpy : 1.20.2

使用教本
Pythonによる新しいデータ分析の教科書

エラーの経緯
教本p219を参考に以下のデータフレームを作成

import pandas as pd
import numpy as np
df = pd.DataFrame({'A': np.arange(1,6),'B': ['a','b','c','b','c']})
df

sklearnを使って、B列のa,b,c,d,eでOneHotEncodeする
(文字列変数を数値データに変換したい)

#データフレームのカテゴリ変数を数値化したい
from sklearn.preprocessing import LabelEncoder,OneHotEncoder

#defaultでdeep=trueなので、深い複製
df_ohe = df.copy()
#ラベルエンコーダーをインスタンス化
le = LabelEncoder()
#B列の値を数値化
df_ohe['B']=le.fit_transform(df_ohe['B'])

ohe = OneHotEncoder(categorical_features=[1])
ohe.fit_transform(df_ohe.toarray())

以下のエラーが発生

TypeError: __init__() got an unexpected keyword argument 'ColumnTransformer'

先生、LabelEncodingとOneHotEncodingの違いからわからないです。。。
ということでまとめました。
エンコーダーの公式ドキュメントも確認してね

Labelエンコーダー

文字列の項目を数値に変換

イメージ

#LabelEncoding
#①このようなモデルを作って
ラベル : [りんご,ごりら,らっぱ]
ラベルID : [1,2,3]
#②この配列を作る
[ごりら,ごりら,らっぱ]
#①ラベルを適用してLabelEncoding
[2,2,3]

OneHotエンコーダー

文字列の項目の有無を0,1で新しい列を作成

#OneHotEncoding
#①このようなモデルを作る
A:[0,1,2,3,4]
B:[a,b,c,d,e]
#②このモデルをOneHotencoding
A:[0,1,2,3,4]
B_a:[1,0,0,0,0]
B_b:[0,1,0,0,0]
B_c:[0,0,1,0,0]
B_d:[0,0,0,1,0]
B_e:[0,0,0,0,1]
#列の項目のカテゴリ別に0,1の配列が作成される
#このように0が多い行列を疎行列という(<>密行列)

本題

このエラーはなんだったのか
#エラー
TypeError: __init__() got an unexpected keyword argument 'ColumnTransformer'

原因
教本の環境が今のバージョンと異なっており、OneHotEncoderの仕様が変わり
categorical_featuresはバージョン0.22で排除済だった

#教本
scikit-learn===0.19.1
#使用する環境
scikit-learn===0.24.2

よって公式例を参考にして以下でOneHotEncodingを実践しました

from sklearn.preprocessing import OneHotEncoder
import pandas as pd
#データフレーム作成
import numpy as np
df = pd.DataFrame({
    'A': np.arange(1,6),
    'B': ['a','b','c','b','c']
})

df_ohe = df.copy()
#特に引数はいらないみたい
ohe = OneHotEncoder()
ohe.fit_transform(df_ohe).toarray()

結果はscipy.sparse型の行列なので人間の私にはわかりにくい
ちなみにOneHotEncodingのインスタンス時に'sparse = False'にするとNumpy.ndarrayの一次元配列になる

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

カラム名のつけたデータフレーム型に変換して表示してみた

OnehotEncode型のデータを複数のカテゴリ名を持つデータフレームに変換する仕方がわからなかったので、ここではカテゴリが一つの配列をOneHotEncodingした疎行列データをデータフレームに変換します。

#データの準備
from sklearn.preprocessing import OneHotEncoder
import pandas as pd
import numpy as np

df = pd.DataFrame({
    'A': np.arange(1,6),
    'B': ['a','b','c','b','c']
})
#OneHotEncoderのインスタンス化
ohe = OneHotEncoder()
#yにデータフレームのB列のndarray型の配列を代入
y = df.B.values
#yを5行1列にしたものをOneHotEncoding
#OneHotEncodingは二次元以上の配列しかできないので元々1次元のyを変換する必要があった
ohe.fit(y.reshape(-1,1))

#OneHotEncodingしたoheインスタンスをtransformでコミットしたcsr.csr_matrix型のデータをy_dataに代入
y_data = ohe.transform(y.reshape(-1,1))

#DataFrame型で再定義
#引数のデータにはy_dataをndarray型に変換したもの
#引数のカラム名はOneHotEncoder型のデータoheがCategories_として保持しているもの
y_df = pd.DataFrame(y_data.toarray(),columns=ohe.categories_)
y_df


結果
なんとかOneHotEncodeしたデータをカラム名をつけて表現できた。

スクリーンショット 2021-05-07 22.48.52.png

今後調べること


疎行列で(5,1)の構造であるcsr.csr_matrix型のデータをtoarray()関数でndarray型にしたら、(5,3)の構造になったのは何故か


エンコード方法は調べただけでも沢山存在しているらしく、他にはどんなエンコードがどんな状況で使われるのか

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0