pandasでカンマ区切りの値や正規化されたデータをダミー変数に変換を行う


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

この場合、ダミー変数へ変換を行うと user24が重複してしまいます。

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