概要
sklearn.preprocessing
のOrdinalEncoder
は、2次元のデータ(行数×列数=データ数×特徴量数)を須知ラベルデータに変換する。
- コンストラクターでencoderのインスタンスを生成
fit()
メソッドに2次元の元データを与える(元データは2次元のリスト、ndarray、DataFrame
は可)- 元データの特徴量ごと(列ごと)にデータが数値ラベル化される
- 特徴量のカテゴリー数が
n_class
のとき、特徴量データが0~n_class
−1の整数ラベルに変換される - 1次元のデータを変換する場合も2次元に変形する必要がある
- 変換は全ての列が対象となり、定量的な数値データが含まれていてもそれらが数値ラベルに変換される
使い方
fit~ラベルの設定
以下の例では、3つの特徴量を持つ6つのデータを例題としている。特徴量は3つともクラスデータで、fit()
メソッドで変換器の準備をする。
- エンコーダーにおける
fit()
は、特徴量ごとにクラスデータのラベルを設定し、変換器を準備する - フィッティングの後、
categories_
プロパティーにリストがセットされる categories_
はndarray
を要素とするリストで、各配列には特徴量ごとの重複を除いたクラス名が格納される- 各特徴量のクラスは
categories_
各要素の配列の先頭から数値ラベル0, 1, 2, …に対応している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
from sklearn.preprocessing import OrdinalEncoder X = [ ["Tokyo", "Male", "by air"], ["Tokyo", "Male", "by rail"], ["Osaka", "Female", "by rail"], ["Kyoto", "Female", "by bus"], ["Osaka", "Male", "by air"], ["Osaka", "Female", "by bus"] ] oe = OrdinalEncoder() oe.fit(X) print(oe.categories_) print(oe.categories_[0]) print(oe.categories_[1]) print(oe.categories_[2]) # [array(['Kyoto', 'Osaka', 'Tokyo'], dtype=object), array(['Female', 'Male'], dtype=object), array(['by air', 'by bus', 'by rail'], dtype=object)] # ['Kyoto' 'Osaka' 'Tokyo'] # ['Female' 'Male'] # ['by air' 'by bus' 'by rail'] |
transform~ラベルへの変換
この変換器のtransform()
メソッドで元データを変換すると、元データと同じ次元・次数の2次元配列が得られ、各クラスデータが数値データに変換された結果が格納されている。
なお、OrdinalEncoder
にもfit_transform()
メソッドが準備されている。
1 2 3 4 5 6 7 8 9 |
X_trans = oe.transform(X) print(X_trans) # [[2. 1. 0.] # [2. 1. 2.] # [1. 0. 2.] # [0. 0. 1.] # [1. 1. 0.] # [1. 0. 1.]] |
1次元のデータを変換する場合でも、1×1の2次元とする必要があり、結果も2次元の配列で返される。
1 2 3 4 5 |
y = [["Kyoto", "Male", "by rail"]] y_trans = oe.transform(y) print(y_trans) # [[0. 1. 2.]] |
inverse_transform()
で数値ラベルをクラスデータに逆変換可能。
1 2 3 |
print(oe.inverse_transform(y_trans)) # [['Kyoto' 'Male' 'by rail']] |
categories_パラメーターについて
なおコンストラクターのcategories_
パラメーターを指定できるが、これはあらかじめ特徴量のクラスデータがわかっている場合に、これらを全特徴量について指定する。この際、元データに含まれないクラスを含めてもよい。
1 2 3 4 5 |
oe = OrdinalEncoder(categories=[ ["Tokyo", "Kyoto", "Osaka", "Nagoya"], ["Male", "Female"], ["by air", "by bus", "by rail"]]) oe.fit(X) |
数値データとクラスデータが混在する場合
クラスデータと数値データが混在する場合にOrdinalEncoder
で変換すると、すべてのデータがクラスデータとみなされ、数値データもラベルに変換されてしまう。
以下の例では、最後の列の実数データも、1, 1.5, …, 5に対して0, 1, …, 5のラベルに変換されている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
X = [ ["Tokyo", "Male", "by air", 1.5], ["Tokyo", "Male", "by rail", 3], ["Osaka", "Female", "by rail", 3.5], ["Kyoto", "Female", "by bus", 5], ["Osaka", "Male", "by air", 1], ["Osaka", "Female", "by bus", 4] ] oe = OrdinalEncoder() oe.fit(X) X_trans = oe.transform(X) print(X_trans) # [[2. 1. 0. 1.] # [2. 1. 2. 2.] # [1. 0. 2. 3.] # [0. 0. 1. 5.] # [1. 1. 0. 0.] # [1. 0. 1. 4.]] |
このような場合は、クラスデータのみ取り出して変換させる。OrdinalEncoder
はpandas.DataFrame
を扱うことができるので、列操作のために元データをDataFrame
とする。
1 2 3 4 5 6 7 8 9 10 11 |
import pandas as pd df = pd.DataFrame(X, columns=["city", "gender", "transportation", "travel_time"]) print(df) # city gender transportation travel_time # 0 Tokyo Male by air 1.5 # 1 Tokyo Male by rail 3.0 # 2 Osaka Female by rail 3.5 # 3 Kyoto Female by bus 5.0 # 4 Osaka Male by air 1.0 # 5 Osaka Female by bus 4.0 |
今回の例では、最初の3列がクラスデータなので、一時的なDataFrame
にそれらを切出してOrdinalEncoder
を適用する。transform()
の結果はndarray
で戻るので、それを元のDataFrame
の列に入れ替えている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
df_temp = df[["city", "gender", "transportation"]] oe.fit(df_temp) df_trans = oe.transform(df_temp) print(df_trans) print() df[["city", "gender", "transportation"]] = df_trans print(df) # [[2. 1. 0.] # [2. 1. 2.] # [1. 0. 2.] # [0. 0. 1.] # [1. 1. 0.] # [1. 0. 1.]] # # city gender transportation travel_time # 0 2.0 1.0 0.0 1.5 # 1 2.0 1.0 2.0 3.0 # 2 1.0 0.0 2.0 3.5 # 3 0.0 0.0 1.0 5.0 # 4 1.0 1.0 0.0 1.0 # 5 1.0 0.0 1.0 4.0 |
最後の列はそのままで、その前の3列がラベルデータに変換されている。