ダミー変数変換(Dummy Variable Encoding)は One-Hot Encoding とも呼ばれるデータ変換手法です。
pandas では get_dummies メソッドを使うと、以下のようにダミー変数へ変換できます。
df = pd.DataFrame({'user': [1,2,3],
'flag': ['a','b','a']})
pd.get_dummies(df['flag'])
| a | b | |
|---|---|---|
| 0 | 1 | 0 |
| 1 | 0 | 1 |
| 2 | 1 | 0 |
文字列の値をバイナリ値の複数列に変換します。
カンマ区切りの値が入っている場合の変換方法
次に、以下のようなカンマ区切りで値を持っているデータフレームでダミー変数への変換を行おうとする場合、
df = pd.DataFrame({'user': [1,2,3,4,5],
'opt1': [100,200,200,400,100],
'opt2': ['a', 'a,b', 'c', 'b,c', 'b']})
| user | opt1 | opt2 | |
|---|---|---|---|
| 0 | 1 | 100 | a |
| 1 | 2 | 200 | a,b |
| 2 | 3 | 200 | c |
| 3 | 4 | 400 | b,c |
| 4 | 5 | 100 | b |
対象のカラムをカンマ区切りで変換します。(わかりやすいように opt2_ プレフィックスをつけてます)
df2 = df['opt2'].str.get_dummies(sep=',').add_prefix('opt2_')
| opt2_a | opt2_b | opt2_c | |
|---|---|---|---|
| 0 | 1 | 0 | 0 |
| 1 | 1 | 1 | 0 |
| 2 | 0 | 0 | 1 |
| 3 | 0 | 1 | 1 |
| 4 | 0 | 1 | 0 |
参考: pandas.Series.str.get_dummies
これを元のデータフレームから必要なカラムだけ取り出してから結合して完成です。
df3 = pd.concat([df[['user', 'opt1']], df2], axis=1)
| user | opt1 | opt2_a | opt2_b | opt2_c | |
|---|---|---|---|---|---|
| 0 | 1 | 100 | 1 | 0 | 0 |
| 1 | 2 | 200 | 1 | 1 | 0 |
| 2 | 3 | 200 | 0 | 0 | 1 |
| 3 | 4 | 400 | 0 | 1 | 1 |
| 4 | 5 | 100 | 0 | 1 | 0 |
正規化されたデータの場合
リレーショナルデータベースからデータを取得する場合は、正規化されていることがほとんどです。
以下のように2つのテーブルのデータに対してダミー変数への変換を行います。
df1 = pd.DataFrame({'user': [1,2,3,4,5],
'opt1': [100,200,200,400,100]})
df2 = pd.DataFrame({'user': [1,2,2,3,4,4,5],
'opt2': ['a','a','b','c','b','c','b']})
display(df1, df2)
| user | opt1 | |
|---|---|---|
| 0 | 1 | 100 |
| 1 | 2 | 200 |
| 2 | 3 | 200 |
| 3 | 4 | 400 |
| 4 | 5 | 100 |
| user | opt2 | |
|---|---|---|
| 0 | 1 | a |
| 1 | 2 | a |
| 2 | 2 | b |
| 3 | 3 | c |
| 4 | 4 | b |
| 5 | 4 | c |
| 6 | 5 | b |
この場合、ダミー変数へ変換を行うと userの2と4が重複してしまいます。
pd.get_dummies(df2, columns=['opt2'], prefix='opt2')
| user | opt2_a | opt2_b | opt2_c | |
|---|---|---|---|---|
| 0 | 1 | 1 | 0 | 0 |
| 1 | 2 | 1 | 0 | 0 |
| 2 | 2 | 0 | 1 | 0 |
| 3 | 3 | 0 | 0 | 1 |
| 4 | 4 | 0 | 1 | 0 |
| 5 | 4 | 0 | 0 | 1 |
| 6 | 5 | 0 | 1 | 0 |
そのため、groupby して sum で集約します。
df3 = pd.get_dummies(df2, columns=['opt2'], prefix='opt2').groupby('user').sum()
| user | opt2_a | opt2_b | opt2_c |
|---|---|---|---|
| 1 | 1 | 0 | 0 |
| 2 | 1 | 1 | 0 |
| 3 | 0 | 0 | 1 |
| 4 | 0 | 1 | 1 |
| 5 | 0 | 1 | 0 |
最後に元のデータにマージして完成です。
df4 = df1.merge(df3, on='user')
| user | opt1 | opt2_a | opt2_b | opt2_c | |
|---|---|---|---|---|---|
| 0 | 1 | 100 | 1 | 0 | 0 |
| 1 | 2 | 200 | 1 | 1 | 0 |
| 2 | 3 | 200 | 0 | 0 | 1 |
| 3 | 4 | 400 | 0 | 1 | 1 |
| 4 | 5 | 100 | 0 | 1 | 0 |