Python環境を起動中... 初回のみ数秒かかります
Lesson 10 / 12

groupbyでグループ集計

このレッスンで学ぶこと

  • groupbyの「分割→適用→結合」の考え方を理解できる
  • グループごとの平均・件数などを集計できる
  • agg で複数の集計を同時に行える
  • pivot_table でクロス集計表を作れる

1. 「グループごと」に集計する

これまでは「全体の平均」を求めてきましたが、実際の分析では 「病棟ごとの平均」「年代ごとの傾向」「診断名ごとの件数」のように、 グループに分けて集計したい場面がほとんどです。これを実現するのが groupby です。

groupbyの動作は、「分割(Split)→ 適用(Apply)→ 結合(Combine)」の3ステップで理解できます。

📊 groupbyの3ステップ:

  1. 分割:データを指定したキー(病棟など)でグループに分ける
  2. 適用:各グループに集計(平均・合計など)を適用する
  3. 結合:各グループの結果を1つの表にまとめる

「Excelのピボットテーブルをコードで行う」イメージです。一度覚えると、分析の幅が一気に広がります。 この3ステップが実際のコードのどこに当たるかは、次のセクションで具体的に確認します。

2. groupby の基本

df.groupby("グループのキー")["集計したい列"].集計関数() が基本の形です。 「病棟ごとにSBPの平均」を求めるなら df.groupby("病棟")["SBP"].mean() と書きます。

📊 3ステップがコードのどこに対応するか: さきほどの「分割 → 適用 → 結合」は、df.groupby("病棟")["SBP"].mean() の各部分にそのまま対応します。

  • .groupby("病棟")① 分割:病棟(A・B・C)ごとのグループに分ける
  • ["SBP"] → 集計の対象にする列を選ぶ
  • .mean()② 適用:各グループのSBPに平均を計算する
  • (結果が1つの表になる)→ ③ 結合:pandasが自動でまとめてくれる

つまり「分けて → 計算して → まとめる」を、たった1行で書いているわけです。

sample_1.py
Ctrl+Enter
出力

💡 結果のindexはグループのキー: groupby("病棟") の結果は、病棟(A・B・C)がindexになった集計表(Series)です。 「A病棟の平均SBPは130」とすぐ読み取れます。 このように、グループごとの数字を1行で出せるのがgroupbyの強力なところです。

3. agg — 複数の集計を同時に

「平均だけでなく、最大・件数も一度に知りたい」——そんなときは agg(["集計1", "集計2", ...]) を使います。 複数の集計関数をリストで渡すと、それぞれの結果が列として並びます。

sample_2.py
Ctrl+Enter
出力

🩺 医療データ文脈: 「病棟ごとに、患者数・平均血圧・最高血圧をまとめて見たい」といったサマリ表の作成は、 groupby + agg の定番用途です。日々の集計レポートや、部門別の比較分析で大活躍します。

💡 結果の列名を指定する(名前付き集計): df.groupby("病棟").agg(平均SBP=("SBP","mean"), 件数=("SBP","count")) のように、 新しい列名=("対象列", "集計法") の形でも書けます。こう書くと結果の列名を自分で決められ、 「SBPは平均、BMIは最大」のように列ごとに違う集計も指定できます。このあとの自由練習で実際に使っています。

4. pivot_table — クロス集計表を作る

pivot_table は、Excelのピボットテーブルと同じクロス集計表を作れます。 「行に病棟、列に診断名、値に平均SBP」のような、2つの軸で集計した表を一発で作成できます。

sample_3.py
Ctrl+Enter
出力

💡 groupby と pivot_table の使い分け:

  • groupby … 1つの軸でグループ集計(病棟ごと)。シンプルで柔軟
  • pivot_table … 2つの軸でクロス集計(病棟 × 診断名)。表形式で見やすい

該当する組み合わせがないセルは NaN になります(例:C病棟に糖尿病の患者がいなければ空欄)。

5. 練習問題

問題 1

診断名ごとの平均SBPを求めよう

下記の df を、groupby診断名ごとのSBPの平均を求めて表示してください。

exercise_1.py
出力
ヒントを見る(答え+解説)
import pandas as pd

df = pd.DataFrame({
    "診断名": ["高血圧","糖尿病","高血圧","健常","高血圧","糖尿病"],
    "SBP":   [140, 150, 150, 118, 160, 130],
})

# 診断名ごとのSBPの平均を求めて表示してください
print(df.groupby("診断名")["SBP"].mean())
# 健常=118.0, 糖尿病=140.0, 高血圧=150.0

groupby("診断名")["SBP"].mean() で、診断名ごとにSBPの平均が出ます。高血圧グループ(140,150,160)の平均は150.0、糖尿病(150,130)は140.0、健常(118)は118.0です。

問題 2

病棟ごとに複数集計しよう

下記の df を、agg病棟ごとのBMIの「平均・最大・件数」をまとめて表示してください。

exercise_2.py
出力
ヒントを見る(答え+解説)
import pandas as pd

df = pd.DataFrame({
    "病棟": ["A", "A", "B", "B", "C"],
    "BMI":  [22.0, 24.0, 28.0, 30.0, 25.0],
})

# 病棟ごとのBMIの「平均・最大・件数」を agg で表示してください
print(df.groupby("病棟")["BMI"].agg(["mean", "max", "count"]))
# A: mean=23.0, max=24.0, count=2
# B: mean=29.0, max=30.0, count=2
# C: mean=25.0, max=25.0, count=1

agg(["mean","max","count"]) で、複数の集計を同時に行えます。A病棟のBMI平均は(22+24)/2=23.0、B病棟は(28+30)/2=29.0です。サマリ表作成の定番パターンです。

問題 3

pivot_tableでクロス集計しよう

下記の df から、行=性別、列=診断名、値=SBPの平均のクロス集計表を pivot_table で作ってください。

exercise_3.py
出力
ヒントを見る(答え+解説)
import pandas as pd

df = pd.DataFrame({
    "性別":   ["男", "女", "男", "女"],
    "診断名": ["高血圧", "高血圧", "糖尿病", "糖尿病"],
    "SBP":    [150, 140, 130, 120],
})

# 行=性別、列=診断名、値=SBP平均 のクロス集計表を作ってください
pv = df.pivot_table(values="SBP", index="性別", columns="診断名", aggfunc="mean")
print(pv)

pivot_tablevalues(値)・index(行)・columns(列)・aggfunc(集計方法)を指定します。性別×診断名の組み合わせごとに、平均SBPが表になって出ます。

6. まとめ

このレッスンのポイント

  • groupbyは「分割 → 適用 → 結合」の3ステップでグループ集計する
  • df.groupby("キー")["列"].mean() でグループごとの集計ができる
  • agg(["mean","max","count"]) で複数集計を同時に
  • pivot_table で2軸のクロス集計表を作れる(行×列)
  • 1軸ならgroupby、2軸ならpivot_tableが見やすい

自由に試してみましょう:

free_practice.py
出力

完了するとコース一覧に進捗が記録されます