pandas

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

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

pandasのDataFrameでpivot_tableを使ってピボットテーブルを扱う方法について解説します。

pivot_tableによるピボットテーブルの作成

表形式のデータを扱う際に良く行われる操作としてピボットテーブルがあります。pandasのDataFrameではピボットテーブルを作成するためにpivot_tableという便利な関数が用意されています。本記事ではpivot_tableの基本的な使用方法を紹介します。

以降でpivot_tableの使い方を紹介する際には、以下の簡単なcsvデータを用います。想定するのは企業での売上一覧データで、各製品がいつ、どこに、いくらで売られたかをまとめているものと思ってください。このデータを使って、製品ごと、顧客ごと等で整理したピボットテーブルを作る例を紹介します。

pandas pivot_table サンプルデータ
Note

pivot_tableの公式ドキュメントの記載はこちらを参照してください。

基本的なpivot_tableの使い方

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

ピボットテーブル (pivot_table) 例

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) 例

複数レベルを指定して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の使い方は是非覚えていただけるとよいかと思います。