【Pandasデータ集計】pivot_table()で複雑なクロス集計も自由自在!カテゴリごとの統計量を算出


 

データ分析において、「複数のカテゴリを軸にして、それぞれの組み合わせにおける合計値や平均値などの統計量を算出したい」というニーズは非常に頻繁に発生します。例えば、「地域別・商品カテゴリ別の月間売上合計」や「性別・年代別の平均購買額」といった、多軸での集計と分析です。

Pandasの**pivot_table()関数**は、Excelのピボットテーブルのように、複数の列を「行」「列」「値」「集計方法」に割り当てて、柔軟かつ強力な集計表(ピボットテーブル)を作成するための機能です。この記事では、pivot_table()の基本的な使い方から、知っておくと便利な応用例まで、短いサンプルコードと丁寧な解説を交えてご紹介します。


 

pivot_table()とは?なぜ多軸集計に不可欠なのか?

 

pivot_table()は、DataFrameのデータを指定した「行(インデックス)」「列(カラム)」「値(バリュー)」、そして「集計関数(アグリゲーション関数)」に基づいて再構築し、新しいDataFrameとして出力します。これにより、多次元のデータをコンパクトな表形式にまとめることができます。

pivot_table()が多軸集計に不可欠な理由は以下の通りです。

  • 多角的な分析: 複数の視点からデータを集計し、複雑なビジネス課題やデータの関係性を明らかにできます。

  • 柔軟な集計: 合計、平均、カウントなど、様々な統計量を適用でき、必要に応じて独自の集計関数も利用できます。

  • レポート作成の効率化: 分析結果をすぐに表形式で出力できるため、レポートやダッシュボードの基礎データとして非常に役立ちます。

  • データ探索: 異なるカテゴリの組み合わせを試すことで、新たな洞察を発見できます。


 

pivot_table()の基本的な使い方

 

pivot_table()はPandasの関数として提供されており、pd.pivot_table()として使用します。主要な引数は以下の通りです。

  • data: 集計対象となるDataFrame。

  • values: 集計したい値が含まれる列名。

  • index: 新しいピボットテーブルの行(インデックス)にしたい列名。リストで複数指定可能。

  • columns: 新しいピボットテーブルの列にしたい列名。リストで複数指定可能。

  • aggfunc: 集計関数(デフォルトは'mean')。'sum', 'count', 'min', 'max'などの文字列や、NumPy関数、カスタム関数を指定可能。辞書で列ごとに異なる関数を指定することも可能。

 

2つのカテゴリでシンプルに集計する

 

まずは、最も基本的な使い方として、行と列にそれぞれ1つのカテゴリを指定して集計してみましょう。

Python
 
import pandas as pd
import numpy as np

# サンプルDataFrameの作成
df = pd.DataFrame({
    '支店': ['東京', '大阪', '東京', '大阪', '東京'],
    '商品カテゴリ': ['A', 'B', 'A', 'C', 'B'],
    '売上': [100, 150, 120, 80, 200],
    '顧客数': [10, 15, 12, 8, 20]
})
print("オリジナルDataFrame:\n", df)

# '支店'を行、'商品カテゴリ'を列、'売上'を値として合計を算出
pivot_sales = pd.pivot_table(df, values='売上', index='支店', columns='商品カテゴリ', aggfunc='sum')
print("\n支店と商品カテゴリごとの売上合計:\n", pivot_sales)

解説:

  1. values='売上': 集計の対象となる数値列は'売上'です。

  2. index='支店': ピボットテーブルの行インデックスには'支店'の値が使われます。

  3. columns='商品カテゴリ': ピボットテーブルの列ヘッダーには'商品カテゴリ'の値が使われます。

  4. aggfunc=’sum’: 各組み合わせ(例: 東京支店のカテゴリA)の’売上’を合計します。

    結果として、指定した2つのカテゴリを軸にした集計表が生成され、欠損値(該当データがない組み合わせ)はNaNになります。


 

pivot_table()の応用的な使い方

 

pivot_table()は、さらに複雑な集計ニーズにも対応できます。

 

複数の行・列で多次元集計する

 

indexcolumnsに列名のリストを渡すことで、MultiIndex(複数階層のインデックスやカラム)を持つピボットテーブルを作成できます。

Python
 
df_multi = pd.DataFrame({
    '地域': ['東京', '大阪', '東京', '大阪', '東京', '大阪'],
    '商品カテゴリ': ['A', 'B', 'A', 'C', 'B', 'A'],
    '月': ['1月', '1月', '2月', '2月', '1月', '2月'],
    '売上': [100, 150, 120, 80, 200, 110],
    '利益': [10, 15, 12, 8, 20, 11]
})
print("\nオリジナルDataFrame (多軸用):\n", df_multi)

# '地域'と'月'を行、'商品カテゴリ'を列、'売上'を合計
pivot_multi_index = pd.pivot_table(
    df_multi,
    values='売上',
    index=['地域', '月'],    # 行に複数カテゴリ
    columns='商品カテゴリ',
    aggfunc='sum'
)
print("\n地域と月ごとの商品カテゴリ別売上合計:\n", pivot_multi_index)

解説:

index=[‘地域’, ‘月’]とすることで、行インデックスが’地域’と’月’の組み合わせのMultiIndexになり、より詳細な集計が可能になります。

 

複数の値を異なる集計関数で算出する

 

valuesに列名のリストを、aggfuncに辞書形式で列ごとに異なる集計関数を指定することも可能です。

Python
 
# '支店'を行、'商品カテゴリ'を列
# '売上'は合計、'顧客数'は平均を算出
pivot_multi_agg = pd.pivot_table(
    df,
    values=['売上', '顧客数'],  # 複数の値
    index='支店',
    columns='商品カテゴリ',
    aggfunc={'売上': 'sum', '顧客数': 'mean'} # 列ごとに異なる集計関数
)
print("\n支店と商品カテゴリごとの売上合計と顧客数平均:\n", pivot_multi_agg)

解説:

aggfuncに辞書を渡すことで、’売上’列は’sum’で、’顧客数’列は’mean’で集計され、MultiIndexの列を持つDataFrameが生成されます。

 

欠損値(NaN)の扱い: fill_value引数

 

集計結果でデータが存在しない組み合わせはNaNになります。これを特定の任意の値(例: 0)で埋めたい場合はfill_valueを使います。

Python
 
# NaNを0で埋める
pivot_filled = pd.pivot_table(df, values='売上', index='支店', columns='商品カテゴリ', aggfunc='sum', fill_value=0)
print("\nNaNを0で埋めたピボットテーブル:\n", pivot_filled)

解説:

fill_value=0とすることで、データが存在しない組み合わせのセルには0が表示され、表全体が見やすくなります。

 

行/列の小計(総計)を追加する: margins=True

 

集計結果に行や列の総計(または小計)を追加したい場合はmargins=Trueを指定します。

Python
 
# 行と列に総計を追加
pivot_with_margins = pd.pivot_table(df, values='売上', index='支店', columns='商品カテゴリ', aggfunc='sum', margins=True)
print("\n総計付きピボットテーブル:\n", pivot_with_margins)

解説:

margins=Trueとすることで、行と列にそれぞれ’All’というラベルの総計行・列が追加されます。これは、データ全体の合計値を把握するのに非常に便利です。


 

pivot_table()groupby()crosstab()の違い

 

これら3つの関数は似たような集計目的で使われますが、それぞれに得意な領域があります。

  • pivot_table():

    • 最も柔軟で多機能。

    • 複数のindexcolumnsvaluesaggfuncを自由に組み合わせられる。

    • 集計したい数値データが明確に存在する場合に最適。

    • 結果は常にDataFrame。

  • groupby():

    • 最も汎用的なグループ化集計の基本。

    • 特定の列を基準にデータをグループ化し、様々な集計関数を適用する。

    • 結果はSeriesまたはDataFrame(MultiIndexを持つことが多い)。

    • 単純な集計から複雑なグループごとの変換まで幅広い。

  • crosstab():

    • 主に2つ以上のカテゴリ変数の度数分布や関連性を簡潔に表示したい場合に特化。

    • normalize引数による割合算出が強力。

    • **度数(カウント)**の集計が主目的。valuesaggfuncを使えば数値集計も可能だが、pivot_table()の方が一般的。

目的に合わせて適切な関数を選ぶことが重要ですが、多くの複雑な集計ニーズにはpivot_table()が強力な選択肢となります。


 

まとめ

 

Pandasのpivot_table()関数は、Excelのピボットテーブルのように、DataFrameのデータを複数のカテゴリを軸にして柔軟に集計するための非常に強力なツールです。values, index, columns, aggfuncといった主要な引数を使いこなすことで、単一の集計から多次元の複雑な集計、さらには複数の統計量の同時算出まで、幅広い分析ニーズに対応できます。fill_valuemarginsで結果の表示を調整することも可能です。このpivot_table()をマスターすることで、データの深層にある関係性を明らかにし、より洞察に富んだ分析を進めることができるでしょう。