Pandasはデータサイエンスや業務効率化の現場において、統計情報を抽出するために欠かせないライブラリです。
特にgroupbyメソッドは、膨大なデータを特定のカテゴリごとに分類し、要約統計量を算出する際に極めて重要な役割を果たします。
実務においては、単一の列に対して平均値を出すだけでなく、複数の列に対して異なる統計量を同時に適用したい場面が多くあります。
本記事では、Pandasのgroupbyを活用して、複数列・複数指標を効率的に集計する実用的な手法について詳しく紹介します。
初心者の方から、より高度なデータ加工を目指す中級者の方まで、すぐに活用できるコード例を交えて解説を進めます。
Pandasにおけるgroupby集計の基本構造
Pandasのgroupbyは、「分割(Split)」「適用(Apply)」「結合(Combine)」という3つのステップで動作します。
まず、指定したキーに基づいてデータフレームがグループごとに分割されます。
次に、それぞれのグループに対して合計や平均といった計算処理が適用されます。
最後に、計算結果が新しいデータフレームとして再結合される仕組みです。
単純な集計であれば、df.groupby('category').mean()のように記述するだけで完了します。
しかし、実務のデータ分析では、売上には「合計」を、客数には「平均」をといった具合に、列ごとに異なる指標を求める必要が生じます。
このような柔軟な処理を実現するためには、agg(aggregate)メソッドの使いこなしが不可欠となります。
aggメソッドを用いた複数指標の同時算出
aggメソッドを使用すると、一つのグループ化操作に対して複数の集計関数を一度に適用できます。
まずは、特定の列に対して複数の統計量を算出する基本的な方法を見ていきましょう。
import pandas as pd
import numpy as np
# サンプルデータの作成
df = pd.DataFrame({
'支店': ['東京', '東京', '大阪', '大阪', '名古屋', '名古屋'],
'売上': [100, 150, 200, 180, 120, 130],
'利益': [20, 35, 40, 30, 15, 25]
})
# 売上に対して合計と平均、最大値を一度に算出
result = df.groupby('支店')['売上'].agg(['sum', 'mean', 'max'])
print(result)
sum mean max
支店
名古屋 250 125.0 130
大阪 380 190.0 200
東京 250 125.0 150
このように、リスト形式で関数名を渡すことで、複数の指標が横並びで出力されます。
標準的な関数であれば、文字列(’sum’や’mean’など)で指定できるため、記述が非常にシンプルです。
辞書形式による列ごとの集計の最適化
さらに実戦的な手法として、列ごとに異なる集計関数を割り当てる「辞書形式」の指定方法があります。
この方法を用いれば、不要な計算を省きつつ、必要なデータだけを効率的に抽出することが可能です。
# 列ごとに異なる集計を適用
# 売上は「合計」、利益は「平均」を算出
agg_dict = {
'売上': 'sum',
'利益': 'mean'
}
result_custom = df.groupby('支店').agg(agg_dict)
print(result_custom)
売上 利益
支店
名古屋 250 20.0
大阪 380 35.0
東京 250 27.5
特定の列には複数の関数を、別の列には一つの関数を適用するといった柔軟な構成も辞書形式で実現できます。
例えば、'売上': ['sum', 'max']のように記述することで、さらに詳細なレポート作成が可能になります。
Named Aggregationで列名をわかりやすく定義する
複数の集計を行うと、デフォルトでは列名が階層構造(マルチインデックス)になることがあります。
マルチインデックスは見た目が複雑になりやすく、その後のデータ処理で手間取ることが少なくありません。
Pandas 0.25以降で導入されたNamed Aggregation(名前付き集計)を利用すれば、集計と同時に列名のリネームを行えます。
# 集計と同時にわかりやすい列名を付与
result_named = df.groupby('支店').agg(
売上合計=('売上', 'sum'),
利益平均=('利益', 'mean'),
最高売上=('売上', 'max')
)
print(result_named)
売上合計 利益平均 最高売上
支店
名古屋 250 20.0 130
大阪 380 35.0 200
東京 250 27.5 150
この手法の最大のメリットは、出力結果の列名が1階層(フラット)になることです。
これにより、集計直後にそのままCSV出力したり、グラフ描画ライブラリに渡したりする際のコードが劇的に簡潔になります。
ラムダ式(lambda)を用いた高度なカスタム集計
標準の統計関数だけでは不十分な場合、自作の関数やラムダ式を適用することも可能です。
例えば、グループ内の「最大値と最小値の差」を求めたい場合などは、ラムダ式が非常に便利です。
# ラムダ式を用いたカスタム指標の追加
result_lambda = df.groupby('支店').agg({
'売上': lambda x: x.max() - x.min()
})
result_lambda.rename(columns={'売上': '売上レンジ'}, inplace=True)
print(result_lambda)
売上レンジ
支店
名古屋 10
大阪 20
東京 50
ただし、ラムダ式は非常に強力ですが、大規模なデータセットに対して使用すると処理速度が低下する傾向があります。
可能な限りPandasやNumPyの組み込み関数を優先して使用することが、効率的なコーディングのコツです。
集計後のインデックス操作とデータ整形
groupbyによる集計が終わった直後のデータは、グループ化したキーがインデックス(行名)になっています。
多くの分析タスクでは、このインデックスを通常の列に戻した方が扱いやすい場合が多いでしょう。
その際に役立つのが、reset_index()メソッドです。
# インデックスをリセットして通常の列に戻す
final_df = result_named.reset_index()
print(final_df)
支店 売上合計 利益平均 最高売上
0 名古屋 250 20.0 130
1 大阪 380 35.0 200
2 東京 250 27.5 150
また、集計時にas_index=Falseを指定することでも、最初からインデックスを保持しない形式で出力できます。
プロジェクトの要件に合わせて、これらの手法を使い分けるようにしましょう。
大量のデータを扱う際のパフォーマンス最適化
2026年のデータ分析環境においても、データの肥大化に伴う処理速度の低下は常に課題となります。
groupbyを高速化するためには、集計の前に必要な列だけを抽出しておくことが重要です。
データフレーム全体に対してgroupbyを実行すると、計算に関係のない列まで処理対象に含まれ、メモリを無駄に消費してしまいます。
また、数値データの場合は適切なデータ型(int32やfloat32など)に変換しておくことで、計算効率がさらに向上します。
| 手法 | メリット | 注意点 |
|---|---|---|
| 組み込み関数 (‘sum’, ‘mean’) | 非常に高速でメモリ効率が良い | 複雑なロジックは実装不可 |
| Named Aggregation | コードが可読性が高く、後処理が楽 | 記述量が増える場合がある |
| ラムダ式 (lambda) | 自由自在なロジックを適用可能 | 大規模データで低速になる |
上記の表を参考に、データ量と分析の複雑さに応じた最適なアプローチを選択してください。
まとめ
Pandasのgroupbyとaggメソッドを組み合わせることで、複雑な条件でのデータ集計を驚くほど簡単に実行できるようになります。
特に、辞書形式での指定やNamed Aggregationを活用すれば、可読性の高いコードで効率的に分析を進めることが可能です。
まずは基本となるリスト形式の集計から始め、慣れてきたらNamed Aggregationで出力の美しさを追求してみてください。
適切な手法を選択することは、コードの保守性を高めるだけでなく、将来的なデータ規模の拡大にも耐えうるシステム構築に繋がります。
今回紹介したテクニックを駆使して、日々のデータ分析業務をよりスピーディーかつ正確なものにしていきましょう。
