【pandas】DataFrameのpivot_tableでピボットテーブルを扱う

pandasのDataFrameでpivot_tableを使ってピボットテーブルを扱う方法について解説します。
目次
pivot_tableによるピボットテーブルの作成
表形式のデータを扱う際に良く行われる操作としてピボットテーブルがあります。ピボットテーブルは主にExcel等の表計算やDB管理で使用される視覚化ツールです。データの分類や整理、集約といったことが効率的にできるとともに、視覚的にデータの構造を理解しやすくなります。
pandasのDataFrameではピボットテーブルを作成するためにpivot_tableという便利な関数が用意されています。本記事ではpivot_tableの基本的な使用方法を紹介します。
以降でpivot_tableの使い方を紹介するために、以下の簡単なcsvデータを用います。想定するのは企業での売上一覧データで、各製品がいつ、どこに、いくらで売られたかをまとめているものをイメージしてください。このデータを使って、製品ごと、顧客ごと等で整理したピボットテーブルを作る例を紹介していきます。

基本的なpivot_tableの使い方
上記で説明したサンプルデータ(sample.csv)を読み込み、各製品ごとの各月売上合計となる以下のようなピボットテーブルを作ってみることを考えてみます。

DataFrameのデータに対してpivot_tableを使ってピボットテーブルを作るには以下のようにします。
【sample.csv】
no,product_code,client,date,price 1,A,顧客1,2022/03/01,1000 2,A,顧客2,2022/03/01,1000 3,B,顧客1,2022/03/01,500 4,B,顧客1,2022/03/01,500 5,C,顧客1,2022/03/01,2000 6,A,顧客2,2022/03/15,1000 7,A,顧客2,2022/03/15,1000 8,C,顧客3,2022/03/15,2000 9,B,顧客2,2022/03/31,500 10,B,顧客2,2022/03/31,500 11,B,顧客2,2022/03/31,500 12,A,顧客1,2022/04/01,1000 13,A,顧客1,2022/04/01,1000 14,B,顧客1,2022/04/01,500 15,C,顧客1,2022/04/10,2000 16,C,顧客3,2022/04/10,2000 17,C,顧客3,2022/04/10,2000 18,A,顧客1,2022/04/30,1000 19,A,顧客2,2022/04/30,1000 20,B,顧客1,2022/04/30,500
【pivot_tableの使用方法】
import pandas as pd
# ===== サンプルデータの読み込み
df = pd.read_csv('sample.csv')
# print(df)
# print(df.dtypes)
# ===== データ加工
# 日付列をdatetimeに変更
df['date'] = pd.to_datetime(df['date'])
# 年・月・日の列を作成
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
# ===== pivot_table
pt = df.pivot_table('price',
index='product_code',
columns='month',
aggfunc='sum')
print(pt)【実行結果】 month 3 4 product_code A 4000 4000 B 2500 1000 C 4000 6000
サンプルデータ読込ではpandasのread_csv関数を使用しています。データの内容を確認したい場合は、コメントアウトしているprintのコメントを外して確認してみてください。
年月日の情報を使用したいため、日付列をto_datetime関数で変換した後に「年("year")」「月("month")」「日("day")」に該当する列情報を事前に作成しています。
ピボットテーブルを作るためにpivot_tableを使用している部分は以下の部分です。
# ===== pivot_table
pt = df.pivot_table('price',
index='product_code',
columns='month',
aggfunc='sum')まずは集約する価格("price")を指定します。次にインデックス(index=)で製品コード("product_code")、列(columns=)で月("month")を順に指定しています。これによりピボットテーブルにおける行方向と列方向の種類が決まります。
次に指定している集約関数(aggfunc=)では、集約するときに使用する関数を指定します。今回は合計するための"sum"を指定しています。aggfuncのデフォルト設定は平均("mean")になっていますのでaggfuncを指定しない場合には平均が計算されます。aggfuncには他にも"count"、"min"、"max"などが指定できます。
上記のようにpivot_tableを使用することで簡単にピボットテーブルを作成することが可能です。
多重ピボットテーブル(複数レベルの指定)
上記ではシンプルなピボットテーブルの例を見てきました。今度は、複数レベルを指定して多重のピボットテーブルを作る例を見てみましょう。
具体的には、以下のように行方向は「製品コード("product_code")」「顧客("client")」の順の階層で、列方向は「年("year")」「月("month")」「日("day")」の順の階層で価格の合計を整理してみます。

複数レベルを指定してpivot_tableを使った多重ピボットテーブルを作るには以下のようにします。
import pandas as pd
# ===== サンプルデータの読み込み
df = pd.read_csv('sample.csv')
# print(df)
# print(df.dtypes)
# ===== データ加工
# 日付列をdatetimeに変更
df['date'] = pd.to_datetime(df['date'])
# 年・月・日の列を作成
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
# ===== pivot_table(複数レベルでの指定)
pt = df.pivot_table('price',
index=['product_code', 'client'],
columns=['year', 'month', 'day'],
aggfunc='sum')
# NaN部分を0で埋めて表示
print(pt.fillna(0))【実行結果】
year 2022
month 3 4
day 1 15 31 1 10 30
product_code client
A 顧客1 1000.0 0.0 0.0 2000.0 0.0 1000.0
顧客2 1000.0 2000.0 0.0 0.0 0.0 1000.0
B 顧客1 1000.0 0.0 0.0 500.0 0.0 500.0
顧客2 0.0 0.0 1500.0 0.0 0.0 0.0
C 顧客1 2000.0 0.0 0.0 0.0 2000.0 0.0
顧客3 0.0 2000.0 0.0 0.0 4000.0 0.0データ加工で年・月・日等の列を事前に用意しているところは、先ほど紹介の例と同様です。ピボットテーブルを作るためにpivot_tableを使用している部分は以下の部分になります。
# ===== pivot_table(複数レベルでの指定)
pt = df.pivot_table('price',
index=['product_code', 'client'],
columns=['year', 'month', 'day'],
aggfunc='sum')基本的な使い方は先ほどの例と同様ですが、異なるのはindex=とcolumns=で各階層になる列名をリストで順に指定している部分です。
このようにpivot_tableの引数の指定方法を少し変えるだけで、複数レベルの階層で集約したピボットテーブルも簡単に作ることが可能です。
[参考] groupbyでピボットテーブルを作成する方法
pivot_tableの使用方法について紹介しました。ピボットテーブルは集約の考え方を使っているためgroupbyを使用してピボットテーブルを実現することももちろん可能です。
groupbyの基本的な使い方については「DataFrameをgroupbyでグループ化して集約する方法」でまとめていますので参考にしてください。
ピボットテーブルは、groupbyでの集計の多次元集計版ともいえる方法なのでgroupbyで実現できます。これまでにpivot_tableにて実現した処理と同じ動作をするgroupbyでの実装例は以下のようになります。
import pandas as pd
# ===== サンプルデータの読み込み
df = pd.read_csv('sample.csv')
# print(df)
# print(df.dtypes)
# ===== データ加工
# 日付列をdatetimeに変更
df['date'] = pd.to_datetime(df['date'])
# 年・月・日の列を作成
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
# マニュアルでpivot_tableを作成
print(df.groupby(['product_code', 'month'])['price'].sum().unstack())【実行結果】 month 3 4 product_code A 4000 4000 B 2500 1000 C 4000 6000
ピボットテーブルを作るためにgroupbyを使った加工をしているのは以下の部分になります。
# マニュアルでpivot_tableを作成 print(df.groupby(['product_code', 'month'])['price'].sum().unstack())
この部分では、groupbyでまず製品コード("product_code")と月("month")を指定してグループを作成し、グループの中から価格("price")列に対してsum()による合計を出しています。sum()までのコードでは以下のDataFrameが出来上がっています。
product_code month
A 3 4000
4 4000
B 3 2500
4 1000
C 3 4000
4 6000このDataFrameに対してunstack()によりmonth列の部分を列方向に展開することでピボットテーブルの結果と同じような結果を取得しています。1行で書いてしまうと途中の処理が分からないという方は途中まででprint表示しつつ確認してみると分かりやすいでしょう。
このようにgroupbyを使ってもピボットテーブルは作成可能です。ただし、コードは少し読みにくく、直感的には何をしているか分かりにくいと感じられるかなと思います。pivot_tableを使用する方が簡潔に処理を記載できるのでpivot_tableの使い方は是非覚えていただけるとよいかと思います。
まとめ
pandasのDataFrameでpivot_tableを使ってピボットテーブルを扱う方法について解説しました。
表形式のデータを扱う際に良く行われる操作としてピボットテーブルを使うとで他の分類や集約した状況を視覚的に確認することができます。pandasでは、pivot_tableで簡単に作成できますので、例を使って紹介しました。
また、groupbyを使ってもピボットテーブルを作成できるものの、pivot_tableの方がより簡単にピボットテーブルが作成できることを見ていただきました。
ピボットテーブルはデータの状況を確認、分析する際によく使用するツールです。pandasでも簡単に作成できますので、是非使い方を覚えてもらえればと思います。
pivot_tableの公式ドキュメントはこちらを参照してください。
上記で紹介しているソースコードについてはgithubにて公開しています。参考にしていただければと思います。







