Open In Colab

カテゴリデータの処理#

本節ではpandasを利用したカテゴリデータの処理方法を学びます。

データ(変数)は質的変数(カテゴリ変数)、量的変数(連続変数)に分類されます。

量的変数は数や量で測れる変数で、間隔尺度と比例尺度に分類されます。

間隔尺度

気温や順位など、和や差に意味があるが比率には意味がない尺度(0の意味がない)

比例尺度

身長や重さなど、和や差、比率に意味がある尺度

質的変数は離散的な値をとり、数値では表現できない変数で、名義尺度と順序尺度に分類されます。

名義尺度

血液型や性別など、和や差、比率に意味がなく、比較ができない尺度

順序尺度

震度や企業格付など、比較できるが、和や差、比率に意味がない尺度

import pandas as pd
import plotly.express as px

tips = px.data.tips()
tips.head()
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4

Category型#

tips オブジェクトの「sex」列、「smoker」列は名義尺度のため、カテゴリ変数として扱います。Seriesではカテゴリ変数を扱うCategory型が利用できます。

sex = tips.loc[:, "sex"].astype("category")
sex.dtype
CategoricalDtype(categories=['Female', 'Male'], ordered=False)
smoker = tips.loc[:, "smoker"].astype("category")
smoker.dtype
CategoricalDtype(categories=['No', 'Yes'], ordered=False)

tips オブジェクトの「day」列は名義尺度のため、カテゴリ変数として扱います。Category型の生成時に順序を付けられます。

day_of_week = pd.CategoricalDtype(
    categories=["Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"],
    ordered=True
)
day = tips.loc[:, "day"].astype(day_of_week)
day
0       Sun
1       Sun
2       Sun
3       Sun
4       Sun
       ... 
239     Sat
240     Sat
241     Sat
242     Sat
243    Thur
Name: day, Length: 244, dtype: category
Categories (7, object): ['Sun' < 'Mon' < 'Tue' < 'Wed' < 'Thur' < 'Fri' < 'Sat']

順序が付いたCategory型のSeriesは sort_value メソッドによるソートが行えます。

day.sort_values()
0      Sun
172    Sun
173    Sun
174    Sun
175    Sun
      ... 
64     Sat
65     Sat
66     Sat
56     Sat
57     Sat
Name: day, Length: 244, dtype: category
Categories (7, object): ['Sun' < 'Mon' < 'Tue' < 'Wed' < 'Thur' < 'Fri' < 'Sat']

カテゴリデータの変数変換#

機械学習などのモデルによっては、質的変数を数値に変換する必要があります。 get_dummies 関数では文字列やカテゴリデータを数値に変換します。

pd.get_dummies(smoker)
No Yes
0 1 0
1 1 0
2 1 0
3 1 0
4 1 0
... ... ...
239 1 0
240 0 1
241 0 1
242 1 0
243 1 0

244 rows × 2 columns

pd.get_dummies(day)
Sun Mon Tue Wed Thur Fri Sat
0 1 0 0 0 0 0 0
1 1 0 0 0 0 0 0
2 1 0 0 0 0 0 0
3 1 0 0 0 0 0 0
4 1 0 0 0 0 0 0
... ... ... ... ... ... ... ...
239 0 0 0 0 0 0 1
240 0 0 0 0 0 0 1
241 0 0 0 0 0 0 1
242 0 0 0 0 0 0 1
243 0 0 0 0 1 0 0

244 rows × 7 columns

pd.get_dummies(tips.loc[:, "time"])
Dinner Lunch
0 1 0
1 1 0
2 1 0
3 1 0
4 1 0
... ... ...
239 1 0
240 1 0
241 1 0
242 1 0
243 1 0

244 rows × 2 columns

pd.get_dummies(tips.loc[:, ["sex", "smoker"]])
sex_Female sex_Male smoker_No smoker_Yes
0 1 0 1 0
1 0 1 1 0
2 0 1 1 0
3 0 1 1 0
4 1 0 1 0
... ... ... ... ...
239 0 1 1 0
240 1 0 0 1
241 0 1 0 1
242 0 1 1 0
243 1 0 1 0

244 rows × 4 columns

カテゴリデータの分析#

質的変数を数値に変換することで、回帰分析などの分析が行えます。

次のコードでは散布図行列に可視化し、2変数の関係を可視化しています。

tips_converted = pd.concat(
    [
        tips.select_dtypes(include=["int", "float"]),
        pd.get_dummies(tips.select_dtypes(exclude=["int", "float"]))
    ],
    axis=1
)
px.scatter_matrix(tips_converted, height=1200)
/home/vscode/.local/lib/python3.11/site-packages/plotly/express/_core.py:279: FutureWarning:

iteritems is deprecated and will be removed in a future version. Use .items instead.
tips_converted.corr()
total_bill tip size sex_Female sex_Male smoker_No smoker_Yes day_Fri day_Sat day_Sun day_Thur time_Dinner time_Lunch
total_bill 1.000000 0.675734 0.598315 -0.144877 0.144877 -0.085721 0.085721 -0.086168 0.054919 0.122953 -0.138174 0.183118 -0.183118
tip 0.675734 1.000000 0.489299 -0.088862 0.088862 -0.005929 0.005929 -0.055463 -0.002790 0.125114 -0.095879 0.121629 -0.121629
size 0.598315 0.489299 1.000000 -0.086195 0.086195 0.133178 -0.133178 -0.142184 -0.041121 0.193054 -0.072598 0.103411 -0.103411
sex_Female -0.144877 -0.088862 -0.086195 1.000000 -1.000000 0.002816 -0.002816 0.071060 -0.053957 -0.168106 0.194445 -0.205231 0.205231
sex_Male 0.144877 0.088862 0.086195 -1.000000 1.000000 -0.002816 0.002816 -0.071060 0.053957 0.168106 -0.194445 0.205231 -0.205231
smoker_No -0.085721 -0.005929 0.133178 0.002816 -0.002816 1.000000 -1.000000 -0.244316 -0.155744 0.181624 0.128534 -0.054921 0.054921
smoker_Yes 0.085721 0.005929 -0.133178 -0.002816 0.002816 -1.000000 1.000000 0.244316 0.155744 -0.181624 -0.128534 0.054921 -0.054921
day_Fri -0.086168 -0.055463 -0.142184 0.071060 -0.071060 -0.244316 0.244316 1.000000 -0.216319 -0.195451 -0.169608 -0.058159 0.058159
day_Sat 0.054919 -0.002790 -0.041121 -0.053957 0.053957 -0.155744 0.155744 -0.216319 1.000000 -0.500682 -0.434480 0.462709 -0.462709
day_Sun 0.122953 0.125114 0.193054 -0.168106 0.168106 0.181624 -0.181624 -0.195451 -0.500682 1.000000 -0.392566 0.418071 -0.418071
day_Thur -0.138174 -0.095879 -0.072598 0.194445 -0.194445 0.128534 -0.128534 -0.169608 -0.434480 -0.392566 1.000000 -0.917996 0.917996
time_Dinner 0.183118 0.121629 0.103411 -0.205231 0.205231 -0.054921 0.054921 -0.058159 0.462709 0.418071 -0.917996 1.000000 -1.000000
time_Lunch -0.183118 -0.121629 -0.103411 0.205231 -0.205231 0.054921 -0.054921 0.058159 -0.462709 -0.418071 0.917996 -1.000000 1.000000
px.imshow(
    tips_converted.corr().values,
    x=tips_converted.corr().columns,
    y=tips_converted.corr().index,
    text_auto=True,
    width=800,
    height=800
)