ピボットテーブルとクロス集計
ピポットテーブルは、表計算プログラムやその他のデータ分析ソフトウェアでよく見られるデータの要約ツールです。ピポットテーブルでは、データは1つ以上のキーによってテーブル形式のデータを集約し、特定のグループキーを行に対して、また別のグループキーを列に対して整理し、全体として長方形の形にデータを整形します。pandasにおけるピポットテーブルは、groupbyの機能と階層型のインデックスを操作する再形成機能の組み合わせで実現されています。
code: Python
import pandas as pd
tips = pd.read_csv('tips.csv')
# 総支払額に占めるチップの割合を追加
--------------------------------------------------------------------------
total_bill tip smoker day time size tip_pct
0 16.99 1.01 No Sun Dinner 2 0.059447
1 10.34 1.66 No Sun Dinner 3 0.160542
2 21.01 3.50 No Sun Dinner 3 0.166587
3 23.68 3.31 No Sun Dinner 2 0.139780
4 24.59 3.61 No Sun Dinner 4 0.146808
5 25.29 4.71 No Sun Dinner 4 0.186240
--------------------------------------------------------------------------
dayとsmokerによって整理されたグループの平均値(pivot_tableの集約のデフォルトのタイプ)を計算する場合です。
code: Python
--------------------------------------------------------------------------
size tip tip_pct total_bill
day smoker
Fri No 2.250000 2.812500 0.151650 18.420000
Yes 2.066667 2.714000 0.174783 16.813333
Sat No 2.555556 3.102889 0.158048 19.661778
Yes 2.476190 2.875476 0.147906 21.276667
Sun No 2.929825 3.167895 0.160113 20.506667
Yes 2.578947 3.516842 0.187250 24.120000
Thur No 2.488889 2.673778 0.160298 17.113111
Yes 2.352941 3.030000 0.163863 19.190588
--------------------------------------------------------------------------
tip_pctとsizeだけを集約し、time, dayごとにグループ化します。
code: Python
--------------------------------------------------------------------------
size tip_pct
smoker No Yes No Yes
time day
Dinner Fri 2.000000 2.222222 0.139622 0.165347
Sat 2.555556 2.476190 0.158048 0.147906
Sun 2.929825 2.578947 0.160113 0.187250
Thur 2.000000 NaN 0.159744 NaN
Lunch Fri 3.000000 1.833333 0.187735 0.188937
Thur 2.500000 2.352941 0.160311 0.163863
--------------------------------------------------------------------------
margins=Trueを指定すると、テーブルに小計の情報を追加してくれます。この指定をするとAllという行と列が追加され、その行や列にあるデータの集計値がAllの値として表示されます。
code: Python
--------------------------------------------------------------------------
size tip_pct
smoker No Yes All No Yes All
time day
Dinner Fri 2.000000 2.222222 2.166667 0.139622 0.165347 0.158916
Sat 2.555556 2.476190 2.517241 0.158048 0.147906 0.153152
Sun 2.929825 2.578947 2.842105 0.160113 0.187250 0.166897
Thur 2.000000 NaN 2.000000 0.159744 NaN 0.159744
Lunch Fri 3.000000 1.833333 2.000000 0.187735 0.188937 0.188765
Thur 2.500000 2.352941 2.459016 0.160311 0.163863 0.161301
All 2.668874 2.408602 2.569672 0.159328 0.163196 0.160803
--------------------------------------------------------------------------
異なる集約関数を使うには、aggfuncに関数を渡します。例えば、countやlen関数は、グループのサイズをクロス集計(個数や頻度の集計)する機能を提供します。
code: Python
aggfunc=len, margins=True)
--------------------------------------------------------------------------
day Fri Sat Sun Thur All
time smoker
Dinner No 3.0 45.0 57.0 1.0 106.0
Yes 9.0 42.0 19.0 NaN 70.0
Lunch No 1.0 NaN NaN 44.0 45.0
Yes 6.0 NaN NaN 17.0 23.0
All 19.0 87.0 76.0 62.0 244.0
--------------------------------------------------------------------------
いくつかの組み合わせが空白(もしくは欠損値)だった場合、次のようにfill_valueを指定して穴埋めできます。
code: Python
columns='day', aggfunc='mean', fill_value=0)
クロス集計:crosstab メソッド
クロス集計はピポットテーブルの特殊なケースで、グループの出現頻度を計算するものです。
code: Python
from io import StringIO
data = """\
Sample Nationality Handedness
1 USA Right-handed
2 Japan Left-handed
3 USA Right-handed
4 Japan Right-handed
5 Japan Left-handed
6 Japan Right-handed
7 USA Right-handed
8 USA Left-handed
9 Japan Right-handed
10 USA Right-handed"""
data = pd.read_table(StringIO(data), sep='\s+')
data
--------------------------------------------------------------------------
Sample Nationality Handedness
0 1 USA Right-handed
1 2 Japan Left-handed
2 3 USA Right-handed
3 4 Japan Right-handed
4 5 Japan Left-handed
5 6 Japan Right-handed
6 7 USA Right-handed
7 8 USA Left-handed
8 9 Japan Right-handed
9 10 USA Right-handed
--------------------------------------------------------------------------
このデータを国籍と利き手で集計したい場合、pivot_tableを使うこともできますが、pandas.crosstab関数を使うと便利です。
code: Python
pd.crosstab(data.Nationality, data.Handedness, margins=True)
--------------------------------------------------------------------------
Handedness Left-handed Right-handed All
Nationality
Japan 2 3 5
USA 1 4 5
All 3 7 10
--------------------------------------------------------------------------
crosstabの最初の2つの引数は、配列、シリーズ、配列のリストを使うことができます。
code: Python
--------------------------------------------------------------------------
smoker No Yes All
time day
Dinner Fri 3 9 12
Sat 45 42 87
Sun 57 19 76
Thur 1 0 1
Lunch Fri 1 6 7
Thur 44 17 61
All 151 93 244
--------------------------------------------------------------------------