【Pandas入門 第4回】データ分析の真髄!groupbyを使った集計・グループ化をマスターしよう 🚀
「部署ごとの平均給与や、商品カテゴリ別の売上合計を計算したい!」
「データの中から、特定のグループだけの統計量を簡単に出す方法はないの?」
「データ分析といえば集計だけど、Pandasではどうやるのが効率的なんだろう?」
こんにちは! Pandas探検隊、隊長のPythonistaです! 前回の第3回では、欠損値やデータ型、重複といった現実世界の「汚れた」データに立ち向かうための、データクリーニング術を学びましたね。これで、私たちの手元には分析にかける準備が整った、信頼できる綺麗なデータがあります。
シリーズ第4回の今回は、いよいよデータ分析の核心、「データの集計とグループ化」に挑戦します!その主役となるのが、Pandasで最も強力で頻繁に使われる機能の一つ、groupby()
メソッドです。groupby()
を使いこなせば、「部署ごとの平均年齢」「性別ごとの最高点数」といった、特定の条件でデータをグループに分け、それぞれのグループに対して集計処理を行う、といった操作が驚くほど簡単に行えます。この記事を読めば、あなたは単なるデータの一覧から、意味のある洞察を引き出すための強力な分析手法を手に入れることができます!
1. 準備:モジュールのインポートとサンプルDataFrame
まずは、PandasとNumPyをインポートし、これからの例で使う、少し大きめのサンプルDataFrameを作成しましょう。様々なカテゴリと数値データを含んだ社員データを用意します。
import pandas as pd
import numpy as np
# サンプルデータを作成
data = {
'部署': ['営業', '開発', '営業', '人事', '開発', '営業', '開発', '人事'],
'役職': ['課長', 'エンジニア', '主任', '担当', 'リーダー', '担当', 'エンジニア', '課長'],
'性別': ['男性', '女性', '女性', '男性', '男性', '男性', '男性', '女性'],
'年齢': [42, 29, 33, 25, 38, 28, 31, 45],
'給与(万円)': [800, 650, 600, 450, 750, 500, 680, 820],
'残業時間(月)': [30, 10, 25, 5, 15, 22, 12, 18]
}
df = pd.DataFrame(data)
print("--- 社員データDataFrame ---")
print(df)
2. `groupby()`の基本概念:「分割 - 適用 - 結合」を理解しよう
groupby()
の操作は、内部的に**「分割(Split) - 適用(Apply) - 結合(Combine)」**という3つのステップで実行されています。この概念を理解することが、groupby()
を使いこなす上で非常に重要です。
- 分割 (Split): 指定したキー(例: '部署'列)に基づいて、DataFrameを複数のグループに分割します。(「営業」グループ、「開発」グループ、「人事」グループができる)
- 適用 (Apply): 各グループに対して、個別に何らかの関数(例: 平均値を計算する
mean()
)を適用します。 - 結合 (Combine): 各グループでの計算結果を、一つの新しいDataFrame(またはSeries)にまとめて結合します。
この一連の流れを、Pandasはdf.groupby('キー').集計関数()
というシンプルな書き方で実行してくれます。
3. 単一の列でグループ化する
まずは、一番基本的な「一つの列をキーにしてグループ化し、集計する」方法を見ていきましょう。
3.1. `groupby()`オブジェクトの作成と集計関数の適用
df.groupby('列名')
を実行すると、DataFrameGroupBy
という特殊なオブジェクトが作成されます。このオブジェクト自体を表示してもあまり意味のある情報は得られませんが、このオブジェクトに対して集計関数(sum()
, mean()
, count()
など)を呼び出すことで、初めて意味のある結果が得られます。
# '部署'列でグループ化
dept_group = df.groupby('部署')
# 各部署の平均値を計算 (数値列のみを対象とする)
print("\n--- 部署ごとの平均値 ---")
print(dept_group.mean(numeric_only=True))
# 各部署の合計値を計算 (数値列のみを対象とする)
print("\n--- 部署ごとの合計値 ---")
print(dept_group.sum(numeric_only=True))
3.2. 特定の列に対して集計を行う
多くの場合、「部署ごとの**給与**の平均」のように、特定の列の集計値だけが欲しいはずです。その場合は、グループ化した後に列名を指定します。
# 部署ごとの平均給与を計算 (結果はSeries)
avg_salary_by_dept = df.groupby('部署')['給与(万円)'].mean()
print(f"\n--- 部署ごとの平均給与 ---\n{avg_salary_by_dept}")
# 部署ごとの人数を数える (sizeはNaNも含む全行数、countはNaNを含まない行数)
member_count = df.groupby('部署').size()
print(f"\n--- 部署ごとの人数 ---\n{member_count}")
集計対象を1列に絞ると、結果はインデックスがグループ名になったSeries
として返されます。
4. 複数の列でグループ化する(階層的な集計)
キーとして列名のリストを渡すことで、「部署ごと、さらに性別ごと」のように、複数のレベルでグループ化することができます。これにより、より詳細な分析が可能になります。
# '部署'と'性別'でグループ化し、平均給与を計算
avg_salary_by_dept_gender = df.groupby(['部署', '性別'])['給与(万円)'].mean()
print(f"\n--- 部署・性別ごとの平均給与 ---\n{avg_salary_by_dept_gender}")
# reset_index() を使うと、階層的なインデックスが通常の列に戻り、扱いやすくなることが多い
avg_salary_df = avg_salary_by_dept_gender.reset_index()
print(f"\n--- reset_index()でDataFrame化 ---\n{avg_salary_df}")
複数のキーでグループ化すると、結果のインデックスが階層的(マルチインデックス)になります。.reset_index()
は、これを通常のDataFrameに戻すための便利なテクニックとして覚えておきましょう。
5. 複数の集計を一度に行う:.agg()
メソッド
「平均だけでなく、合計と最大値も一度に見たい」「給与の平均と、残業時間の合計を計算したい」といった、より複雑な集計を行いたい場合に、.agg()
(aggregateの略) メソッドが非常に強力です。
5.1. 1つの列に複数の集計関数を適用
集計関数の名前をリストで渡すことで、複数の集計結果を一度に得られます。
salary_stats = df.groupby('部署')['給与(万円)'].agg(['mean', 'std', 'min', 'max'])
print(f"\n--- 部署ごとの給与統計 (agg) ---\n{salary_stats}")
5.2. 異なる列に異なる集計関数を適用
.agg()
に辞書を渡すことで、列ごとに異なる集計関数を適用するという、非常に柔軟な操作が可能です。
# 部署ごとに、給与の平均と残業時間の合計を計算
summary_by_dept = df.groupby('部署').agg({
'給与(万円)': 'mean',
'残業時間(月)': 'sum'
})
print(f"\n--- 部署ごとの給与平均と残業時間合計 ---\n{summary_by_dept}")
# さらに発展:列名を指定して集計(Named Aggregation)
# Pandas 0.25.0以降で推奨される、より可読性の高い書き方
summary_named = df.groupby('部署').agg(
平均給与=('給与(万円)', 'mean'),
最大年齢=('年齢', 'max'),
合計残業時間=('残業時間(月)', 'sum')
)
print(f"\n--- 名前付き集計 (Named Aggregation) ---\n{summary_named}")
名前付き集計 (Named Aggregation) を使うと、結果のDataFrameの列名を自由に指定できるため、非常に分かりやすくなります。
まとめ:groupby()
でデータから洞察を引き出す!
今回は、Pandas入門シリーズの第4回として、データ分析の核心であるgroupby()
を使った集計とグループ化について学びました。
groupby()
の基本的な考え方である「分割-適用-結合」。- 単一または複数の列をキーとしてデータをグループ化する方法。
sum()
,mean()
,size()
,count()
といった基本的な集計関数の適用。.agg()
メソッドを使った、より柔軟で高度な集計操作。
groupby()
を使いこなせるようになると、生のデータを行や列の単位で眺めるだけでなく、意味のある固まり(グループ)として捉え、そこから特徴や傾向を抽出できるようになります。これは、データから価値のある洞察を引き出すための、非常に重要なスキルです。
さて、これで一つのデータテーブル(DataFrame)内での集計はマスターしました。しかし、実際のデータ分析では、顧客マスタと購買履歴のように、複数のテーブルを組み合わせて分析することが頻繁にあります。
次回、第5回(入門編最終回)では、いよいよ実践編として、複数のDataFrameを結合するmerge
やconcat
、簡単な時系列データの扱い、そしてこれまでの知識を総動員してMatplotlibと連携したデータ可視化までを行います。入門編の集大成となる内容です。お楽しみに!
コメント
コメントを投稿