データ分析 質的変数(カテゴリカル変数)を数値に変換
質的変数(カテゴリカル変数)とは
カテゴリカル変数とは、値がカテゴリーやラベルで表される変数のことです。
これらの変数はカテゴリーごとの区別や分類を目的としています。
例)
- 性別:男性、女性
- 血液型:A型、B型、O型、AB型
- 教育レベル:小学校、中学校、高校、大学
質的変数は 名義尺度 と 順序尺度に分けられます
質的変数
├── 名義尺度 (Nominal scale)
└── 順序尺度 (Ordinal scale)
名義尺度
順序がないカテゴリ変数。カテゴリー間に優劣や順序はない。
性別:男性、女性
血液型:A型、B型、O型、AB型
地域:東京、大阪、福岡
順序尺度
順序があるカテゴリ変数。ただし、カテゴリー間の差の大きさは比較できない。
教育レベル:小学校、中学校、高校、大学
顧客満足度:低、中、高
質的変数を数値に置き換える
データ分析で質的変数を扱う場合、多くの分析モデルでは数値での入力しか受け付けていないため
質的変数を数値に置きかえる必要があります。
方法1. Label Encoding
カテゴリごとに一意の整数値を割り当てます
順序尺度に使うことが多いです。
- 赤 → 0
- 青 → 1
- 緑 → 2
カテゴリ | エンコード値 |
---|---|
赤 | 0 |
青 | 1 |
緑 | 2 |
方法2. One Hot Encoding
各カテゴリに新しい列が作られ、それぞれのカテゴリに対応する列だけが1、それ以外は0になります
名義尺度に追加うことが多いです。
- 赤
- 青
- 緑
カテゴリ | 赤 | 青 | 緑 |
---|---|---|---|
赤 | 1 | 0 | 0 |
青 | 0 | 1 | 0 |
緑 | 0 | 0 | 1 |
One Hot Encodingの実装例
カテゴリ変数を確認します
df.info()
型がobject のものはカテゴリ変数です
DataFrameの select_dtypes メソッドをつかってobject 型の列名を表示します
df.select_dtypes('object').columns
それぞれの列のユニーク値を確認します。
df['性別'].unique()
array(['女性', '男性'], dtype=object)
df['購入形態'].unique()
array(['プレゼント用', '自分用'], dtype=object)
df['購入の目的'].unique()
array(['記念日', '婚約', '日常使い'], dtype=object)
pandasのget_dummiesメソッドを使って、カテゴリカル変数を変換します
df_encoded1 = pd.get_dummies(df)
df_encoded1.head(5)
boolで表示されているので数値に変換します
df_encoded2 = pd.get_dummies(df).astype(int)
df_encoded2.head(5)
One Hot Encoding は、カテゴリの数が多い場合、データが多次元化してしまいます。
たとえば、「購入の目的」というカテゴリ列に
(記念日/婚約/日常使い)と3つの値があれば、1列(1次元)だったデータが3列(3次元)になってしまいます。
そこで、最初のカテゴリを削除することで、データの冗長性を減らすオプションを指定します
df_encoded3 = pd.get_dummies(df, drop_first = True).astype(int)
df_encoded3
One Hot Encoding と Label Encoding を併用する
Label Encoding は sklearn(サーキットラーン)ライブラリ の LabelEncoder クラスを使用します。
性別 (男性/女性) と 職位(主任/係長/課長/部長)のデータを
性別は順位がないので One Hot Encoding で数値化し、
職位は順序があるので Label Encoding で数値化してみます。
import pandas as pd
from sklearn.preprocessing import LabelEncoder
# データフレームの作成
df = pd.DataFrame({
'性別': ['男性', '女性', '男性', '女性'],
'職位': ['主任', '係長', '課長', '部長'],
'年齢': [35, 40, 45, 50]
})
# 性別をOne Hot Encoding
df = pd.get_dummies(df, columns=['性別'], drop_first=True)
df['性別_男性'] = df['性別_男性'].astype(int)
df
index | 職位 | 年齢 | 性別_男性 |
---|---|---|---|
0 | 主任 | 35 | 1 |
1 | 係長 | 40 | 0 |
2 | 課長 | 45 | 1 |
3 | 部長 | 50 | 0 |
# 職位をLabel Encoding
le = LabelEncoder()
df['職位'] = le.fit_transform(df['職位'])
df
index | 職位 | 年齢 | 性別_男性 |
---|---|---|---|
0 | 0 | 35 | 1 |
1 | 1 | 40 | 0 |
2 | 2 | 45 | 1 |
3 | 3 | 50 | 0 |
Discussion