1. 「グループごと」に集計する
これまでは「全体の平均」を求めてきましたが、実際の分析では
「病棟ごとの平均」「年代ごとの傾向」「診断名ごとの件数」のように、
グループに分けて集計したい場面がほとんどです。これを実現するのが groupby です。
groupbyの動作は、「分割(Split)→ 適用(Apply)→ 結合(Combine)」の3ステップで理解できます。
📊 groupbyの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行で書いているわけです。
💡 結果のindexはグループのキー:
groupby("病棟") の結果は、病棟(A・B・C)がindexになった集計表(Series)です。
「A病棟の平均SBPは130」とすぐ読み取れます。
このように、グループごとの数字を1行で出せるのがgroupbyの強力なところです。
3. agg — 複数の集計を同時に
「平均だけでなく、最大・件数も一度に知りたい」——そんなときは agg(["集計1", "集計2", ...]) を使います。
複数の集計関数をリストで渡すと、それぞれの結果が列として並びます。
🩺 医療データ文脈:
「病棟ごとに、患者数・平均血圧・最高血圧をまとめて見たい」といったサマリ表の作成は、
groupby + agg の定番用途です。日々の集計レポートや、部門別の比較分析で大活躍します。
💡 結果の列名を指定する(名前付き集計):
df.groupby("病棟").agg(平均SBP=("SBP","mean"), 件数=("SBP","count")) のように、
新しい列名=("対象列", "集計法") の形でも書けます。こう書くと結果の列名を自分で決められ、
「SBPは平均、BMIは最大」のように列ごとに違う集計も指定できます。このあとの自由練習で実際に使っています。
4. pivot_table — クロス集計表を作る
pivot_table は、Excelのピボットテーブルと同じクロス集計表を作れます。
「行に病棟、列に診断名、値に平均SBP」のような、2つの軸で集計した表を一発で作成できます。
💡 groupby と pivot_table の使い分け:
groupby… 1つの軸でグループ集計(病棟ごと)。シンプルで柔軟pivot_table… 2つの軸でクロス集計(病棟 × 診断名)。表形式で見やすい
該当する組み合わせがないセルは NaN になります(例:C病棟に糖尿病の患者がいなければ空欄)。
5. 練習問題
診断名ごとの平均SBPを求めよう
下記の df を、groupby で診断名ごとのSBPの平均を求めて表示してください。
ヒントを見る(答え+解説)
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です。
病棟ごとに複数集計しよう
下記の df を、agg で病棟ごとのBMIの「平均・最大・件数」をまとめて表示してください。
ヒントを見る(答え+解説)
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です。サマリ表作成の定番パターンです。
pivot_tableでクロス集計しよう
下記の df から、行=性別、列=診断名、値=SBPの平均のクロス集計表を pivot_table で作ってください。
ヒントを見る(答え+解説)
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_table の values(値)・index(行)・columns(列)・aggfunc(集計方法)を指定します。性別×診断名の組み合わせごとに、平均SBPが表になって出ます。
6. まとめ
このレッスンのポイント
- groupbyは「分割 → 適用 → 結合」の3ステップでグループ集計する
df.groupby("キー")["列"].mean()でグループごとの集計ができるagg(["mean","max","count"])で複数集計を同時にpivot_tableで2軸のクロス集計表を作れる(行×列)- 1軸ならgroupby、2軸ならpivot_tableが見やすい
自由に試してみましょう:
完了するとコース一覧に進捗が記録されます