ダミー変数変換(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 |