はじめに
勉強しても勉強してもすぐ忘れてしまうので備忘録兼アウトプット練習のためQiitaに記事を投稿していく。
間違い、より良い方法あればコメント下さるとうれしいです。
発想
機械学習でOne-hot Encodingを実施したいがテストデータにはどんなデータがあるかなどわからない。
One-hot Encodingしたいならget_dummies
を使うと良いとどのサイトにも書いてあるが、例えば
train_df['sex']
にはMale
とFemale
があるがtest_df['sex']
にはMale
しかない
といったとき普通にget_dummies
を使うと作成されるcolumnの数が変わってきてしまう。これはいけない。
そこでいろいろいろいろ調べたところ以下の記事にたどり着いた。
【python】機械学習でpandas.get_dummiesを使ってはいけない
記事自体はget_dummiesを使わず、sklearn
のOneHotEncoder
を使おうというもの。
しかし私はPandas形式のままデータ分析をしてから最終的にNumpy
形式にしたいため、Pandas
のままで何とかしたいというこだわりを持ってしまった。
それが↑の記事のコメントでも解説されており、本記事ではそこを自分なりにかみ砕けるところまで落とす。
実装
実装は結局get_dummies
を使う。
# (i) df_trainのAのuniqueは"hoge"と"fuga"。Bのuniqueは"a"と"b"
df_train = pd.DataFrame({"A": ["hoge", "fuga"], "B": ["a", "b"]})
# (ii) df_trainのAのuniqueは"hoge"と"piyo"。Bのuniqueは"a"と"c"
df_test = pd.DataFrame({"A": ["hoge", "piyo"], "B": ["a", "c"]})
# (iii) CategoricalでAは"hoge"と"fuga"、Bは"a"と"b"だよと決め打ちしてしまう
df_train["A"] = pd.Categorical(df_train["A"], categories=["hoge", "fuga"])
df_train["B"] = pd.Categorical(df_train["B"], categories=["a", "b"])
df_test["A"] = pd.Categorical(df_test["A"], categories=["hoge", "fuga"])
df_test["B"] = pd.Categorical(df_test["B"], categories=["a", "b"])
# (iv) get_dummiesでone-hot
df_train = pd.get_dummies(df_train)
df_test = pd.get_dummies(df_test)
これで最終的にone-hotしたデータは以下のようになる。
df_train
A_hoge A_fuga B_a B_b
0 1 0 1 0
1 0 1 0 1
df_test
A_hoge A_fuga B_a B_b
0 1 0 1 0
1 0 0 0 0
無事、trainのuniqueなものだけでいけた。今回はハードコーディングで対応したが別にunique
を使えばもっとフレキシブルに対応できる。
補足
なぜdf_trainの方もカテゴリを固定しているのかというとこれをしないとhogeとfugaの順番がtrainが逆になってしまうから、である。