【pandas】ピボットテーブルの使い方【pivot・pivot_table】

Excelなどでよく使われるピボットテーブル。
それをpandasのデータフレームで使う場合には

  1. DataFrame.pivot()
  2. DataFrame.pivot_table()

の2種類があります。
今回はピボットテーブルの使い方と2つの関数の違いをご紹介します。

他に似たような機能としてはDataFrame.groupby()があります

この記事のサンプルコード

目次

pivot()とpivot_table()の違いは?

pivot()が簡易版、pivot_table()のほうが沢山の引数を持ち、色々なことができます。
基本的にpivot_table()を使うと考えてよいでしょう。

使い方を見ていきます。

pivot()

DataFrame.pivot(index=None, columns=None, values=None)

まずはデータの準備をします。

flights = sns.load_dataset("flights")
flights.head()
yearmonthpassengers
01949Jan112
11949Feb118
21949Mar132
31949Apr129
41949May121

基本形

インデックス、カラムを指定します。

flights_p = flights.pivot(index="year", columns="month", values=["passengers"])
# もしくは
flights_p = flights.pivot("year", "month","passengers")
flights_p
monthJanFebMarAprMayJunJulAugSepOctNovDec
year
1949112118132129121135148148136119104118
1950115126141135125149170170158133114140
1951145150178163172178199199184162146166
1952171180193181183218230242209191172194
1953196196236235229243264272237211180201
1954204188235227234264302293259229203229
1955242233267269270315364347312274237278
1956284277317313318374413405355306271306
1957315301356348355422465467404347305336
1958340318362348363435491505404359310337
1959360342406396420472548559463407362405
1960417391419461472535622606508461390432

そのままヒートマップにすることもできます。

sns.heatmap(flights_p)

複数項目の表示

より複雑なデータフレームを扱ってみます。

tips = sns.load_dataset("tips")
tips.head()
total_billtipsexsmokerdaytimesize
016.991.01FemaleNoSunDinner2
110.341.66MaleNoSunDinner3
221.013.50MaleNoSunDinner3
323.683.31MaleNoSunDinner2
424.593.61FemaleNoSunDinner4

重複するラベルのエラー

重複する項目があるとエラーが発生します。

tips = tips.pivot("day", "time")
# 重複するラベルがあるとエラーが発生する

なぜ表示できないかというと、重複する項目があると表示できないからです。
このエラーはpivot_table()では表示されません。

pivot_table()は重複した場合、平均値をとります。
しかし、pivot()の場合は値をそのまま表示するからです。

groupbyとの組み合わせで表示

pivot_table()を使えば表示できますが、groupbyとの組み合わせで実現できます。

tips_g = tips.groupby(["day", "time"], as_index=False).sum()
tips_g
daytimetotal_billtipsize
0ThurLunch1077.55168.83150.0
1ThurDinner18.783.002.0
2FriLunch89.9216.6814.0
3FriDinner235.9635.2826.0
4SatLunchNaNNaNNaN
5SatDinner1778.40260.40219.0
6SunLunchNaNNaNNaN
7SunDinner1627.16247.39216.0

groupby()でデータをまとめた後にピボットテーブルで表示してみます。

tips_p = tips_g.pivot("day","time")
tips_p
total_bill tip size
time Lunch Dinner Lunch Dinner Lunch Dinner
day
Thur 1077.55 18.78 168.83 3.00 150.0 2.0
Fri 89.92 235.96 16.68 35.28 14.0 26.0
Sat NaN 1778.40 NaN 260.40 NaN 219.0
Sun NaN 1627.16 NaN 247.39 NaN 216.0

やっと表示できました。おとなしくpivot_table()使ったほうがいいですね・・・。

pivot_table()

DataFrame.pivot_table(values=Noneindex=Nonecolumns=Noneaggfunc='mean'fill_value=Nonemargins=Falsedropna=Truemargins_name='All'observed=False)

先ほどのflightsデータをもう一度扱ってみましょう。

flights.head()
yearmonthpassengers
01949Jan112
11949Feb118
21949Mar132
31949Apr129
41949May121

基本形

flight_pt = flights.pivot_table(index="year", columns="month", values="passengers")
flight_pt
monthJanFebMarAprMayJunJulAugSepOctNovDec
year
1949112118132129121135148148136119104118
1950115126141135125149170170158133114140
1951145150178163172178199199184162146166
1952171180193181183218230242209191172194
1953196196236235229243264272237211180201
1954204188235227234264302293259229203229
1955242233267269270315364347312274237278
1956284277317313318374413405355306271306
1957315301356348355422465467404347305336
1958340318362348363435491505404359310337
1959360342406396420472548559463407362405
1960417391419461472535622606508461390432

pivot()と変わらないです。

複数リストの指定

次はtipsデータ見てみます。

tips.head()
total_billtipsexsmokerdaytimesize
016.991.01FemaleNoSunDinner2
110.341.66MaleNoSunDinner3
221.013.50MaleNoSunDinner3
323.683.31MaleNoSunDinner2
424.593.61FemaleNoSunDinner4

indexやcolumns、valuesはリストで値を渡せます。

tips_pt = tips.pivot_table(index=["time", "day"], 
                          columns=["sex","smoker"], 
                          values="total_bill")
tips_pt
sex Male Female
smoker Yes No Yes No
time day
Lunch Thur 19.171000 18.486500 19.218571 15.899167
Fri 11.386667 NaN 13.260000 15.980000
Dinner Thur NaN NaN NaN 18.780000
Fri 25.892000 17.475000 12.200000 22.750000
Sat 21.837778 19.929063 20.266667 19.003846
Sun 26.141333 20.403256 16.540000 20.824286

欠損値の穴埋め

欠損値の穴埋めは引数にfill_value=""とします。

tips_pt2 = tips.pivot_table(fill_value=0, 
                           index=["time", "day"], 
                           columns=["sex","smoker"], 
                           values="total_bill")
tips_pt2
sex Male Female
smoker Yes No Yes No
time day
Lunch Thur 19.171000 18.486500 19.218571 15.899167
Fri 11.386667 0.000000 13.260000 15.980000
Dinner Thur 0.000000 0.000000 0.000000 18.780000
Fri 25.892000 17.475000 12.200000 22.750000
Sat 21.837778 19.929063 20.266667 19.003846
Sun 26.141333 20.403256 16.540000 20.824286

カテゴリの集計値

各カテゴリの集計値を表示する場合にはmargins=Trueとします。

tips_pt = tips.pivot_table(index=["time", "day"], 
                         columns=["sex"], 
                         values=["total_bill","size"],
                         fill_value=0,
                         margins=True)
tips_pt
size total_bill
sex Male Female All Male Female All
time day
Lunch Thur 2.433333 2.483871 2.459016 18.714667 16.648710 17.664754
Fri 1.666667 2.250000 2.000000 11.386667 13.940000 12.845714
Dinner Thur 0.000000 2.000000 2.000000 0.000000 18.780000 18.780000
Fri 2.285714 2.000000 2.166667 23.487143 14.310000 19.663333
Sat 2.644068 2.250000 2.517241 20.802542 19.680357 20.441379
Sun 2.810345 2.944444 2.842105 21.887241 19.872222 21.410000
All 2.630573 2.459770 2.569672 20.744076 18.056897 19.785943

集計値は引数にaggfuncを指定しない場合、平均値になります。
ALLにも平均値になっていますね。

集計方法の指定

集計方法は引数:aggfunc=""にて指定できます。()は不要です。
合計値を計算してみます。

tips_pt = tips.pivot_table(index=["time", "day"], 
                         columns=["sex"], 
                         values=["total_bill","size"],
                         fill_value=0,
                         margins=True,
                         aggfunc=sum)
tips_pt
size total_bill
sex Male Female All Male Female All
time day
Lunch Thur 73 77 150 561.44 516.11 1077.55
Fri 5 9 14 34.16 55.76 89.92
Dinner Thur 0 2 2 0.00 18.78 18.78
Fri 16 10 26 164.41 71.55 235.96
Sat 156 63 219 1227.35 551.05 1778.40
Sun 163 53 216 1269.46 357.70 1627.16
All 413 214 627 3256.82 1570.95 4827.77

これは便利ですねー。

複数の集計項目

aggfuncにはリストで複数の集計方法を渡せます。

tips_pt = tips.pivot_table(index=["time", "day"], 
                         columns=["sex"], 
                         values=["total_bill"],
                         fill_value=0,
                         margins=True,
                         aggfunc=[sum, max])
tips_pt
sum max
total_bill total_bill
sex Male Female All Male Female All
time day
Lunch Thur 561.44 516.11 1077.55 41.19 43.11 43.11
Fri 34.16 55.76 89.92 13.42 16.27 16.27
Dinner Thur 0.00 18.78 18.78 0.00 18.78 18.78
Fri 164.41 71.55 235.96 40.17 22.75 40.17
Sat 1227.35 551.05 1778.40 50.81 44.30 50.81
Sun 1269.46 357.70 1627.16 48.17 35.26 48.17
All 3256.82 1570.95 4827.77 50.81 44.30 50.81

この記事のサンプルコード

機械学習・データ処理を学ぶのにおすすめの教材

動画で学習するなら!

本気で取り組むならまずは相談!

じっくり書籍で学習するなら!

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!

コメント

コメントする

目次
閉じる