pandas でダミー変数を作成する(get_dummies と OneHotEncoder)

機械学習ではカテゴリカル変数を数値に変換する必要があります。「ダミー変数」や「One-Hot エンコーディング」と呼ばれるこの処理を、pandas の get_dummies と scikit-learn の OneHotEncoder で実装する方法を解説します。

ダミー変数とは

カテゴリ変数の各カテゴリに対して、該当すれば 1、しなければ 0 の列を作成します。

import pandas as pd

df = pd.DataFrame({
    'color': ['', '', '', '', '']
})

# ダミー変数化
dummies = pd.get_dummies(df['color'])
print(dummies)
#    青  緑  赤
# 0   0   0   1
# 1   1   0   0
# 2   0   1   0
# 3   0   0   1
# 4   1   0   0

get_dummies の基本

get_dummies は pandas の関数で、シンプルな変換に適しています。

import pandas as pd

df = pd.DataFrame({
    'name': ['田中', '佐藤', '鈴木'],
    'city': ['東京', '大阪', '東京'],
    'age': [25, 30, 35]
})

# 単一列をダミー変数化
pd.get_dummies(df['city'])

# DataFrame 全体に適用(object 型の列を自動検出)
pd.get_dummies(df)
#    name  age  city_大阪  city_東京
# 0  田中   25        0        1
# 1  佐藤   30        1        0
# 2  鈴木   35        0        1

prefix オプション

複数の列をダミー変数化する場合、prefix で接頭辞をつけると識別しやすくなります。

df = pd.DataFrame({
    'color': ['', '', ''],
    'size': ['S', 'M', 'L']
})

dummies = pd.get_dummies(df, prefix=['color', 'size'])
print(dummies.columns.tolist())
# ['color_赤', 'color_青', 'size_L', 'size_M', 'size_S']

drop_first で多重共線性を回避

回帰分析では、ダミー変数の全てを使うと多重共線性の問題が起きます。drop_first=True で 1 つ目のカテゴリを落とせます。

df = pd.DataFrame({
    'color': ['', '', '', '']
})

# 全カテゴリ
print(pd.get_dummies(df['color']))
#    青  緑  赤
# 0   0   0   1
# 1   1   0   0
# 2   0   1   0
# 3   0   0   1

# 最初のカテゴリを落とす
print(pd.get_dummies(df['color'], drop_first=True))
#    緑  赤
# 0   0   1
# 1   0   0
# 2   1   0
# 3   0   1

「青」の列がなくなりました。緑=0、赤=0 なら青と判断できます。

drop_first=False

全カテゴリを保持。解釈しやすいが、回帰分析で問題になる可能性。

drop_first=True

多重共線性を回避。回帰分析では推奨。

scikit-learn の OneHotEncoder

機械学習パイプラインでは OneHotEncoder がよく使われます。学習データとテストデータで一貫した変換が保証されるためです。

from sklearn.preprocessing import OneHotEncoder
import pandas as pd
import numpy as np

df = pd.DataFrame({
    'color': ['', '', '', '']
})

# OneHotEncoder を作成
encoder = OneHotEncoder(sparse_output=False)

# 学習と変換
encoded = encoder.fit_transform(df[['color']])
print(encoded)
# [[0. 0. 1.]
#  [1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]

# カテゴリの確認
print(encoder.categories_)
# [array(['緑', '赤', '青'], dtype=object)]

未知のカテゴリへの対処

get_dummies の問題点は、学習データにないカテゴリがテストデータに現れたときです。

import pandas as pd

# 学習データ
train = pd.DataFrame({'color': ['', '', '']})
train_dummies = pd.get_dummies(train['color'])

# テストデータに新しいカテゴリ「黄」がある
test = pd.DataFrame({'color': ['', '']})
test_dummies = pd.get_dummies(test['color'])

print(train_dummies.columns.tolist())
# ['緑', '赤', '青']

print(test_dummies.columns.tolist())
# ['赤', '黄']  # 列が一致しない!

OneHotEncoder なら handle_unknown オプションで対処できます。

from sklearn.preprocessing import OneHotEncoder

encoder = OneHotEncoder(sparse_output=False, handle_unknown='ignore')

# 学習データで fit
train = [[''], [''], ['']]
encoder.fit(train)

# 未知のカテゴリを含むデータを変換
test = [[''], ['']]
encoded = encoder.transform(test)
print(encoded)
# [[0. 0. 1.]   # 赤
#  [0. 0. 0.]]  # 黄(全て0になる)
handle_unknown動作
errorエラーを発生(デフォルト)
ignore全て 0 のベクトルにする
infrequent_if_exist稀なカテゴリとして扱う

DataFrame との統合

OneHotEncoder の結果を DataFrame に戻す方法です。

from sklearn.preprocessing import OneHotEncoder
import pandas as pd

df = pd.DataFrame({
    'color': ['', '', ''],
    'size': ['S', 'M', 'L'],
    'price': [100, 200, 300]
})

# カテゴリ列のみエンコード
encoder = OneHotEncoder(sparse_output=False)
cat_columns = ['color', 'size']

encoded = encoder.fit_transform(df[cat_columns])
feature_names = encoder.get_feature_names_out(cat_columns)

# DataFrame に変換して結合
encoded_df = pd.DataFrame(encoded, columns=feature_names)
result = pd.concat([df.drop(columns=cat_columns), encoded_df], axis=1)
print(result)

ColumnTransformer でパイプライン化

実務では ColumnTransformer を使って、カテゴリ列と数値列を別々に処理するのが一般的です。

from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
import pandas as pd

df = pd.DataFrame({
    'color': ['', '', '', ''],
    'size': ['S', 'M', 'L', 'S'],
    'price': [100, 200, 300, 150],
    'target': [0, 1, 1, 0]
})

# 前処理パイプライン
preprocessor = ColumnTransformer(
    transformers=[
        ('cat', OneHotEncoder(handle_unknown='ignore'), ['color', 'size']),
        ('num', StandardScaler(), ['price'])
    ]
)

# モデルと結合
pipeline = Pipeline([
    ('preprocessor', preprocessor),
    ('classifier', LogisticRegression())
])

# 学習
X = df.drop(columns=['target'])
y = df['target']
pipeline.fit(X, y)

# 予測(新しいデータも同じ前処理が適用される)
new_data = pd.DataFrame({
    'color': [''],
    'size': ['M'],
    'price': [250]
})
pipeline.predict(new_data)
get_dummies

探索的分析や簡単な変換に便利。学習/テストの一貫性は手動で管理が必要。

OneHotEncoder

機械学習パイプラインに組み込みやすい。未知カテゴリの処理も可能。

get_dummies は手軽で直感的ですが、本番の機械学習システムでは OneHotEncoder を使ったパイプラインを構築するのが推奨されます。