📊

データ分析 質的変数(カテゴリカル変数)を数値に変換

2024/09/15に公開

質的変数(カテゴリカル変数)とは

カテゴリカル変数とは、値がカテゴリーやラベルで表される変数のことです。
これらの変数はカテゴリーごとの区別や分類を目的としています。
例)

  • 性別:男性、女性
  • 血液型: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