Python、機械学習

【Python】groupby()、pivot_table()の使い方、ビニング処理との併用

グループ分けしてデータの傾向を見たいとき、groupby()やpivot_table()を使います。

どのような場面で使うのか、整理しました。

使用するデータ

説明のために、次のようなデータを作ります。

ドラクエⅢのルイーダの酒場にいる仲間リストを空想で作ったものです。「職業」と「性別」が離散変数、「人気度」が連続変数になります。

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns

data = [
    ['戦士', '男', 7], 
    ['僧侶', '男', 2],
    ['魔法使い', '男', 6],
    ['商人', '男', 4],
    ['遊び人', '男', 0],
    ['戦士', '女', 4],
    ['僧侶', '女', 8],
    ['僧侶', '女', 9],
    ['魔法使い', '女', 4],
    ['商人', '女', 1],
    ['遊び人', '女', 4],
    ['戦士', '男', 9],
    ['僧侶', '男', 3],
    ['戦士', '女', 2]
]

df = pd.DataFrame(data, 
                  columns = ['職業', '性別', '人気度'])
df

groupby()は離散変数が1つのときに使う

1つの離散変数に基づいてグルーピングするときは、groupby()を使います。

例えば、「職業」に基づいてgroupbyをしてみます。

df.groupby('職業').mean()

職業ごとの人気度の平均値を抽出できました。

「性別」に基づいたgroupbyもやってみます。

df.groupby('性別').mean()

mean()の代わりにmax()やmin()を使うことで、平均ではなく最大値、最小値を抽出することができます。また、describe()を使うことで、さまざまな量を一括で表示させることも可能です。

df.groupby('性別').describe()

groupbyの結果を可視化する場合は、棒グラフがよく使われます。

df1 = df.groupby('性別').mean()
sns.barplot(x = df1.index, y = '人気度', data = df1)

このように、1つの離散変数に対して、連続変数の情報(平均値など)をグループ分けして表示させるのがgroupby()の機能です。

pivot_table()は離散変数が2つのときに使う

2つの離散変数に基づいてグルーピングするときは、pivot_table()を使います。

「職業」と「性別」に基づいてpivot_tableをしてみます。

行(index)、列(columns)、表に入れるデータ(values)、表に入れるデータの詳細(aggfunc)を指定します。

pd.pivot_table(
    data = df,
    index = '性別',
    columns = '職業',
    values = '人気度',
    aggfunc= 'mean'
              )

女性の僧侶、男性の戦士に人気が集まっていることがわかります。

pivot_tableの結果を可視化する場合は、ヒートマップがよく使われます。

df2= pd.pivot_table(
    data = df,
    index = '性別',
    columns = '職業',
    values = '人気度',
    aggfunc= 'mean'
              )

sns.heatmap(df2, annot=True, cmap='Purples', fmt="1.1f")

ちなみに、annotとはヒートマップ上に数値を記載するかどうか、cmapはカラーマップの略で「色合い」を、fmtはフォーマットの略で「数値の表記方法」を指定します。

詳しくは、こちらをご参照ください。

【Python】matplotlibとseabornのグラフの書き方の違い、データ分析でよく見るグラフ化手法Pythonでデータ分析するときは、必ずグラフを描きます。 グラフ化することでデータの全体像や特徴をつかんだり、相関関係を把握したり、...

ビニング処理をして連続変数を離散変数に変えてから、グルーピングする

連続変数を離散変数に変えてからグルーピングする方法もよく行われます。

離散変数に変えることをビニング(binning)といいます。binとは棒グラフの棒のことです。連続変数を棒グラフの棒(離散変数)にしましょうということです。

次のように年齢情報を追加したデータでビニングをやってみます。

df['年齢'] = [34, 23, 65, 54, 38, 36, 24, 19, 32, 57, 21, 35, 27, 48]
df

連続変数である「年齢」を離散変数に変えるにはcutやqcutが使われます。

等間隔で分割するのがpd.cut()です。

pd.cut(df['年齢'], 3)

18.954〜34.333歳、34.333〜49.667歳、49.667〜 65.0歳の3カテゴリーに分類してくれました。

分割するしきい値を指定することもできます。

pd.cut(df['年齢'], [0, 30, 50, 70])

また、ラベルをつけることも可能です。

pd.cut(df['年齢'], 
[0, 30, 50, 70],  labels=['若手', '中堅', 'ベテラン'])

qcutを使うと、分割後のカテゴリーに含まれるデータ数が等しくなるようにしてくれます。

pd.qcut(df['年齢'], 3)

最後に、「年齢」を離散化したものに上書きして、groupbyをやってみましょう。

df['年齢'] = pd.cut(df['年齢'], 
[0, 30, 50, 70],  labels=['若手', '中堅', 'ベテラン'])

df.groupby('年代').mean()

うまくできました。