Python Pandasでデータをグループ化して集計する:groupby活用の基本レシピ
はじめに
データ分析において、大量のデータをただ眺めるだけでは、そこから意味のある洞察を得ることは困難です。多くの場合、特定の基準に基づいてデータを「グループ化」し、それぞれのグループ内で合計値や平均値、最大値などの「集計」を行うことで、データの傾向やパターンを明確に把握できるようになります。例えば、顧客の購入履歴データから製品カテゴリごとの総売上を調べたり、地域ごとの平均気温を比較したりする際に、このグループ化と集計の処理が不可欠となります。
この記事では、Pythonのデータ分析ライブラリであるPandasのgroupby()
メソッドを活用し、データを効率的にグループ化して集計する基本的な手順と、その詳細な解説を提供します。このレシピを通じて、お手元のデータを自在に集計し、ビジネスや研究における重要な意思決定に役立てるための第一歩を踏み出せるでしょう。
問題提起:データの集計タスクを効率化したい
あなたは以下のようなデータ分析タスクに直面していませんか。
- ある商品カテゴリごとの総売上を知りたい。
- 各店舗における月ごとの平均顧客数を算出したい。
- 特定の期間における地域別の最大購入額を特定したい。
これらのタスクは、データフレーム全体に対して単純な統計関数を適用するだけでは解決できません。特定の基準(カテゴリ、店舗、月、地域など)でデータを分割し、それぞれのグループ内で集計処理を行う必要があります。手動でデータをフィルタリングしては集計を繰り返す方法は、データ量が増えるにつれて非効率的になり、ミスも発生しやすくなります。
Pandasのgroupby()
メソッドは、このような複雑な集計タスクを効率的かつ正確に実行するための強力なツールです。このメソッドは、「分割(Split)」「適用(Apply)」「結合(Combine)」という3つのステップを経て集計を行います。
解決策(コードレシピ):Pandas groupby()
によるデータ集計
ここでは、架空の売上データを用いて、groupby()
メソッドによる基本的な集計方法を紹介します。
1. 必要なライブラリのインポートとサンプルデータの準備
まず、Pandasライブラリをインポートし、分析に使用するサンプルデータ(DataFrame)を作成します。
import pandas as pd
import numpy as np
# サンプルデータの作成
data = {
'支店': ['東京', '大阪', '東京', '名古屋', '大阪', '東京', '名古屋', '大阪'],
'商品カテゴリ': ['家電', '食品', '家電', '日用品', '食品', '日用品', '家電', '日用品'],
'売上': [10000, 5000, 15000, 3000, 7000, 4000, 12000, 6000],
'数量': [2, 1, 3, 1, 2, 1, 2, 1],
'評価': [4, 5, 3, 4, 5, 3, 4, 4]
}
df = pd.DataFrame(data)
print("元のデータフレーム:")
print(df)
2. 単一の基準でグループ化し、単一の集計関数を適用する
最も基本的な集計方法として、「支店」ごとに「売上」の合計を計算してみましょう。
# 支店ごとの売上合計
sales_by_branch = df.groupby('支店')['売上'].sum()
print("\n支店ごとの売上合計:")
print(sales_by_branch)
3. 複数の基準でグループ化し、単一の集計関数を適用する
次に、「支店」と「商品カテゴリ」の組み合わせごとに「売上」の平均を計算してみます。
# 支店と商品カテゴリごとの売上平均
avg_sales_by_branch_category = df.groupby(['支店', '商品カテゴリ'])['売上'].mean()
print("\n支店と商品カテゴリごとの売上平均:")
print(avg_sales_by_branch_category)
4. 複数の集計関数を適用する(agg()
メソッドの利用)
一つのグループに対して、複数の統計量(合計、平均、個数など)を一度に計算したい場合があります。その際にはagg()
メソッドが非常に便利です。
# 商品カテゴリごとの売上合計、平均、件数を計算
summary_by_category = df.groupby('商品カテゴリ')['売上'].agg(['sum', 'mean', 'count'])
print("\n商品カテゴリごとの売上サマリー:")
print(summary_by_category)
5. agg()
メソッドで列ごとに異なる集計関数を適用し、新しい列名を指定する
さらに柔軟に、異なる列に対して異なる集計関数を適用し、結果の列に分かりやすい名前をつけたい場合は、辞書形式でagg()
メソッドに渡します。
# 支店ごとに、売上合計、数量の平均、評価の最大値を計算
custom_summary_by_branch = df.groupby('支店').agg(
合計売上=('売上', 'sum'),
平均数量=('数量', 'mean'),
最高評価=('評価', 'max')
)
print("\n支店ごとのカスタムサマリー:")
print(custom_summary_by_branch)
6. グループ化結果のインデックスをリセットする
groupby()
の実行結果は、グループ化に使用した列がインデックスとなる場合があります。これを通常のデータ列として扱いたい場合は、reset_index()
を使用します。
# 支店ごとの売上合計を計算し、インデックスをリセット
sales_by_branch_reset = df.groupby('支店')['売上'].sum().reset_index()
print("\n支店ごとの売上合計 (インデックスリセット後):")
print(sales_by_branch_reset)
コードの詳細解説
ここでは、上記のコードレシピで紹介したPandas groupby()
メソッドと関連機能について、一つずつ丁寧に解説していきます。
1. df.groupby('列名')
またはdf.groupby(['列名1', '列名2'])
- 何をするか: データフレーム
df
を、指定した列の値に基づいて複数のグループに分割します。例えばdf.groupby('支店')
とすると、東京
、大阪
、名古屋
という支店
のユニークな値ごとにデータが分かれます。 - なぜ必要か: 集計処理を特定のカテゴリごとに行うための最初のステップです。このメソッド自体はまだ集計を行わず、集計の準備ができた「Groupbyオブジェクト」を返します。
- 引数:
'列名'
(文字列):単一の列でグループ化する場合に指定します。['列名1', '列名2']
(リスト):複数の列の組み合わせでグループ化する場合に指定します。この場合、指定したすべての列の値の組み合わせがユニークなグループを形成します。
2. ['集計対象列名'].集計関数()
- 何をするか:
groupby()
でグループ化された各グループに対して、指定した集計対象列に特定の集計関数(例:sum()
,mean()
,count()
,min()
,max()
,median()
,std()
,var()
など)を適用します。 - なぜ必要か: グループごとに計算された結果を数値として得るためです。例えば、
df.groupby('支店')['売上'].sum()
は、各支店のグループに属する売上
列の値の合計を計算します。 - ポイント:
['集計対象列名']
は、どの列の値を使って集計を行うかを指定します。この部分を省略すると、数値型のすべての列に対して集計関数が適用される場合がありますが、意図しない結果を避けるためにも明示的に指定することをお勧めします。
3. agg()
メソッド
- 何をするか:
groupby()
でグループ化されたデータに対して、複数の集計関数を一度に適用したり、異なる列に異なる集計関数を適用したりする際に使用します。 - なぜ必要か: 一度に多くの情報を集計したい場合に、コードを簡潔にし、効率的に処理を実行できます。
- 引数:
- リスト形式 (
['sum', 'mean', 'count']
): 単一の列に対して複数の集計関数を適用する場合に使用します。結果の列名は、元の列名と集計関数の名前の組み合わせ(例:売上_sum
,売上_mean
)になります。 - 辞書形式 (
{'新しい列名': ('元の列名', '集計関数')}
):新しい列名
: 結果のデータフレームで表示される列名を自由に設定できます。('元の列名', '集計関数')
: どの元の列にどの集計関数を適用するかを指定します。これにより、複数の列に対して異なる集計関数を適用したり、同じ列に対して異なる集計関数を適用して結果の列名をカスタマイズしたりすることが可能です。例えば、合計売上=('売上', 'sum')
は、売上
列の合計を計算し、その結果を合計売上
という新しい列に格納します。
- リスト形式 (
4. reset_index()
- 何をするか:
groupby()
の集計結果は、グループ化に使用した列が新しいデータフレームのインデックスとして設定されることがよくあります。reset_index()
メソッドは、このインデックスを通常のデータ列に戻し、0から始まるデフォルトの整数インデックスを再設定します。 - なぜ必要か: 集計結果をさらにフィルタリングしたり、結合したりする際に、グループ化の基準となった列を通常のデータ列として扱いたい場合に便利です。例えば、
sales_by_branch
のように、支店
がインデックスになっていると、sales_by_branch['東京']
のようにインデックスでアクセスできますが、sales_by_branch_reset[sales_by_branch_reset['支店'] == '東京']
のようにデータ列としてフィルタリングすることもできます。
よくあるエラーとその解決策
KeyError
: グループ化の基準や集計対象として指定した列名がデータフレームに存在しない場合に発生します。列名にスペルミスがないか、大文字・小文字が一致しているかを確認してください。df.columns
で利用可能な列名を確認できます。AttributeError: 'Series' object has no attribute 'sum'
など:groupby()
の結果はGroupbyオブジェクトであり、その後に['列名']
で集計対象の列を選択しないまま集計関数を適用しようとすると、期待しない挙動になることがあります。集計対象の列を明示的に指定するようにしましょう。
まとめ
この記事では、Pandasライブラリのgroupby()
メソッドを用いたデータ集計の基本的なレシピと、その詳細な解説を提供しました。
- 単一の基準と集計: 特定のカテゴリごとの合計や平均を素早く計算できます。
- 複数の基準と集計: 複数のカテゴリの組み合わせによる詳細な分析が可能です。
agg()
メソッドによる高度な集計: 複数の統計量を一度に、または列ごとに異なる集計を適用することで、柔軟なデータサマリーを作成できます。reset_index()
: 集計結果をより扱いやすい形式に整形するのに役立ちます。
groupby()
はデータ分析において非常に強力で頻繁に利用される機能の一つです。このレシピで学んだ知識とコードを活用することで、お手元のデータを様々な角度から分析し、より深い洞察を得ることが可能になります。ぜひ、ご自身のデータで試して、その便利さを実感してください。