pandas の groupby でグループごとに集計する

データ分析では「部署ごとの売上合計」「年代別の平均点」のように、グループごとに集計したい場面がよくあります。pandas の groupby を使えば、このような集計が簡単にできます。

基本的な使い方

groupby でグループ化し、集計関数を呼び出します。

import pandas as pd

df = pd.DataFrame({
    'department': ['Sales', 'Sales', 'Engineering', 'Engineering'],
    'name': ['Alice', 'Bob', 'Charlie', 'Dave'],
    'salary': [50000, 60000, 70000, 80000]
})

result = df.groupby('department')['salary'].sum()
print(result)

このコードでは、department ごとに salary を合計しています。結果は Series として返されます。

よく使う集計関数

groupby の後に呼び出せる集計関数はたくさんあります。

関数説明
sum()合計
mean()平均
count()件数
min()最小値
max()最大値
std()標準偏差
# 部署ごとの平均給与
df.groupby('department')['salary'].mean()

# 部署ごとの人数
df.groupby('department')['name'].count()

複数の集計を一度に行う

agg を使うと、複数の集計を一度に行えます。

result = df.groupby('department')['salary'].agg(['sum', 'mean', 'count'])

列ごとに異なる集計をしたい場合は、辞書で指定します。

result = df.groupby('department').agg({
    'salary': ['sum', 'mean'],
    'name': 'count'
})

複数の列でグループ化する

リストで複数の列を指定すると、組み合わせでグループ化できます。

df = pd.DataFrame({
    'year': [2023, 2023, 2024, 2024],
    'quarter': ['Q1', 'Q2', 'Q1', 'Q2'],
    'sales': [100, 200, 150, 250]
})

result = df.groupby(['year', 'quarter'])['sales'].sum()

結果は MultiIndex の Series になります。

結果をデータフレームに戻す

groupby の結果はグループ化した列がインデックスになります。通常の列に戻したい場合は reset_index() を使います。

result = df.groupby('department')['salary'].sum().reset_index()

as_index=False を指定しても同じ結果になります。

result = df.groupby('department', as_index=False)['salary'].sum()

transform でグループ集計値を元データに追加する

transform を使うと、グループごとの集計値を元の行数のまま取得できます。

df['dept_mean'] = df.groupby('department')['salary'].transform('mean')

各行に「その部署の平均給与」が追加されます。全体平均との差を計算したいときなどに便利です。

filter でグループ単位で絞り込む

filter を使うと、条件を満たすグループだけを残せます。

# 人数が2人以上の部署だけを残す
result = df.groupby('department').filter(lambda x: len(x) >= 2)

groupby は pandas の中でも特に強力な機能です。SQL の GROUP BY に慣れている人なら、すぐに使いこなせるでしょう。