pandasのダミー変数化の挙動
pandasというRのデータフレームやエクセルのようなデータ構造を扱うためのライブラリがある。そのpandasのダミー変数化の関数(pd.get_dummies
)の挙動が、少しわかりにくい部分が*1あったのでここに書いておく。
前提
- Python 3.6.0
- numpy: version 1.11.3
- pandas: version 0.19.2
型が数値(int, float)になっている場合
以下のような DataFrame をまず用意しておく。
>>> d = pd.DataFrame([[i + 5] for i in range(5)], columns=['col']) >>> d col 0 5 1 6 2 7 3 8 4 9
ここでまず、 pd.get_dummies
を d
の col
列にのみ取り出して(pd.Series
にした状態で)作用させてみる。
>>> type(d.col) <class 'pandas.core.series.Series'> >>> pd.get_dummies(d.col) 5 6 7 8 9 0 1 0 0 0 0 1 0 1 0 0 0 2 0 0 1 0 0 3 0 0 0 1 0 4 0 0 0 0 1
このように正常にダミー変数化される。では、1列のDataFrameのままだとどうなるか。実際に実行すると、
>>> type(d) <class 'pandas.core.frame.DataFrame'> >>> pd.get_dummies(d) col 0 5 1 6 2 7 3 8 4 9
このようになる。特に変化はない。
なお、上の例では整数値で行ったが、 float
値のデータフレームを作っても同様の挙動を示す。
なぜこのような挙動を示すか
以下は推測。根拠はない。
これは正常の動作で、おそらく整数や float 型の列と、離散な値をとる列とが混在しているときにダミー変数化しすぎないようにするためだと思われる。
つまり、整数や少数などの数値データとして解釈できる列はダミー変数化はせず、数値データとして扱えない列のみダミー変数化する。要するに以下のような挙動を得るためである。
>>> import pandas as pd >>> df = pd.DataFrame([['a', 1], ['b', 3], ['c', 11]], columns=['A', 'B']) >>> df A B 0 a 1 1 b 3 2 c 11 >>> pd.get_dummies(df) B A_a A_b A_c 0 1 1 0 0 1 3 0 1 0 2 11 0 0 1
上の例では、 A
列は数値でなく、 B
列は数値なので B
列はそのまま、 A
列はダミー変数化される。
もし B
列もダミー変数化したいのであれば型を変換しておけばよい。
>>> df.dtypes A object B int64 dtype: object >>> df.astype(object).dtypes A object B object dtype: object >>> pd.get_dummies(df.astype(object)) A_a A_b A_c B_1 B_3 B_11 0 1 0 0 1 0 0 1 0 1 0 0 1 0 2 0 0 1 0 0 1
一方で、 Series
の場合は型は1種類なので、型が混在するようなことはなく、挙動が型によらずに一定なのだろう。
欠損が混じっている場合
欠損値(np.nan
)が混じっている場合、 pd.get_dummies
をした結果に欠損が残るか残らないかが上記の挙動により変わる*2。具体的には、以下のようになる。
>>> import numpy as np >>> import pandas as pd >>> d = pd.DataFrame([[1], [2], [np.nan]], columns=['col']) >>> d col 0 1.0 1 2.0 2 NaN >>> pd.get_dummies(d) col 0 1.0 1 2.0 2 NaN >>> pd.get_dummies(d.col) 1.0 2.0 0 1 0 1 0 1 2 0 0
欠損値が残っている場合でも、単に float
列のデータフレームには特に何も操作が行われないので、欠損値は残ったままだ。一方で、 Series
の場合はダミー変数化され、すべての列に 0
が入る。これにより欠損を表す列ができていることにはなる*3。
NaNを表す列を作りたければオプションがある:
>>>>>> pd.get_dummies(d.col, dummy_na=True) 1.0 2.0 NaN 0 1 0 0 1 0 1 0 2 0 0 1
結論
- ダミー変数化したい列は明示的に
object
型に変換しておくほうが無難 - NaNと戦うのしんどい