ピボットテーブルとはエクセルで有名な機能の1つで馴染みの方も多いかもしれません。
複雑なデータ構造を一目で分かりやすくする目的でよく使われるもので、クロス集計したものをまとめたものとなります。 2つの要素間の相関が分かりやすく現れるので使いこなせると重宝するでしょう。例えば男女間での科目ごとの平均点といったものをひと目で把握することができます。
Pandasでも手軽にピボットテーブルを作成できるpivot_table
関数が実装されています。
そこで本記事ではpivot_table関数の使い方について解説します。
pivot_table関数
APIドキュメント
まずはAPIドキュメントから見ていきます。
pandas.pivot_table(data, values=None, index=None, columns=None, aggfunc=’mean’, fill_value=None, margins=False, dropna=True, margins_name=’All’)
params:
パラメータ名 | 型 | 概要 |
---|---|---|
data | DataFrame | ピボットテーブルを作成したいデータを選択します。 |
values | カラム | (省略可能)初期値None 集計を行う対象の列データを指定します。 |
index | カラム,Grouper,配列 もしくはこれらのリスト |
(省略可能)初期値None 行ラベルとして使用するものを指定します。 |
columns | カラム,Grouper,配列 もしくはこれらのリスト |
(省略可能)初期値None 列ラベルとして使用するものを指定します。 |
aggfunc | 関数,関数のリスト, 辞書 |
(省略可能)初期値np.mean データを集計する手法を指定します。 |
fill_value | スカラー | (省略可能)初期値None 欠損値を補完する値を指定します。 |
margins | bool値 | (省略可能)初期値False Trueの時列ごとの合計と行ごとの合計を表示します。 |
dropna | bool値 | (省略可能)初期値True 全てのデータがNaN値である列データを集計に含まないようにします。 |
margins_name | str | (省略可能)初期値’All’ 小計を表示する行と列のラベル名を指定します。 |
returns:
ピボットテーブルとなったDataFrameが返されます
引数を見てみると、色々と細かく指定できることが分かります。ただ1つ1つの意味が理解できていればこれらの引数を指定してあげるだけで手軽にピボットテーブルを作成することが可能です。
また、DataFrame.pivot_table
関数も存在しています。data
引数の有無だけの違いなので同一の関数と見なして問題ありません。
ピボットテーブルを作成する
とりあえずピボットテーブルを作成してみましょう。Kaggleのタイタニックのデータを使用します。
このデータから寄港地(Embarked
)と生存したかどうか(Survived
)の値で振り分けたものでの平均年齢を表示させます。
In [1]: import pandas as pd
In [2]: df = pd.read_csv("train.csv") # タイタニックの訓練データを読み込む
In [3]: df.columns # 列ラベルは12個
Out[3]:
Index(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp',
'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'],
dtype='object')
In [5]: pd.pivot_table(df, values="Age",index="Survived", columns="Embarked", aggfunc='mean')
Out[5]:
Embarked C Q S
Survived
0 33.666667 30.325 30.203966
1 28.973671 22.500 28.113184
寄港地と生存したかどうかで分類した中での平均年齢を出すことができました。
C
はフランスのシェルブール,Q
はアイルランドのクイーンズタウン,S
はイギリスのサウサンプトンとなっています。
Survivedの0は生き残れず、1は生き残れたことを表すラベルです。
データを見てみると、生き残った人々の方が平均年齢が若く、クイーンズタウンから乗り込んだ人の間では顕著な差が現れたと読み取れます。
複数要素を元に多層化させる
インデックスラベルとカラムラベルに選択できるデータは複数選択することが可能です。その場合、MultiIndexとして表示されます。
In [10]: pd.pivot_table(df,values="Age",index=["Pclass","Embarked"],columns="Survived")
Out[10]:
Survived 0 1
Pclass Embarked
1 C 43.380952 35.905660
Q 44.000000 33.000000
S 43.845238 34.529091
2 C 29.500000 16.875000
Q 57.000000 30.000000
S 33.603659 26.822027
3 C 26.065217 13.940000
Q 28.083333 19.500000
S 26.484716 22.737705
データの個数をカウントする
では次にこれの人数の内訳を見てみます。aggfunc='count'
とすることで要素数を計算できます。
In [17]: df.pivot_table(index='Survived',columns='Embarked',aggfunc='count') # df.pivot_tableでも使える
Out[17]:
Age Cabin Fare ... Sex SibSp Ticket
Embarked C Q S C Q S C ... S C Q S C Q S
Survived ...
0 51 20 353 17 2 49 75 ... 427 75 47 427 75 47 427
1 79 8 201 52 2 80 93 ... 217 93 30 217 93 30 217
[2 rows x 30 columns]
values
を指定しないとこのようにインデックスとカラムラベルに選択されていないデータ全てを対象にピボットテーブルが作成されます。
今回aggfunc='count'
としているのでそれぞれのデータで有効なものがいくつあったかをカウントしています。
今はAge
での内訳をみたいので、values="Age"
とすれば求めるピボットテーブルが作成されます。
In [23]: df.pivot_table(values="Age",index='Survived',columns='Embarked',aggfunc='count')
Out[23]:
Embarked C Q S
Survived
0 51 20 353
1 79 8 201
列ごとと行ごとの合計を表示
margins=True
にすればそれぞれのデータの合計を表示させることができます。
In [24]: df.pivot_table(values="Age",index="Survived",columns="Embarked",aggfunc="count",margins=True)
Out[24]:
Embarked C Q S All
Survived
0 51 20 353 424
1 79 8 201 288
All 130 28 554 712
デフォルトでは"All"
と表示されます。ここの名前を変更することもできます。margins_name
で設定可能です。
In [25]: df.pivot_table(values="Age",index="Survived",columns="Embarked",aggfunc="count",margins=True, margins_name="total")
Out[25]:
Embarked C Q S total
Survived
0 51 20 353 424
1 79 8 201 288
total 130 28 554 712
複数の統計量を表示させる
今の2つの値を並べて表示させます。aggfunc=["mean","count"]
のようにリストに収めれば可能です。
In [26]: df.pivot_table(values="Age",index='Survived',columns='Embarked',aggfunc=['count', 'mean'])
Out[26]:
count mean
Embarked C Q S C Q S
Survived
0 51 20 353 33.666667 30.325 30.203966
1 79 8 201 28.973671 22.500 28.113184
関数を使って統計処理を指定する
他の関数を使って処理を指定することも可能です。 例としてNumPyの関数を使ってみます。
In [29]: df.pivot_table(values="Age",index='Survived',columns='Embarked',aggfunc=[np.mean,np.std]) # 平均と標準偏差を表示
Out[29]:
mean std
Embarked C Q S C Q S
Survived
0 33.666667 30.325 30.203966 14.990553 19.212986 13.711031
1 28.973671 22.500 28.113184 15.530733 7.191265 14.812722
欠損値を補完
fill_value
で欠損値します。以下のようなCabin
とEmbarked
で仕分けた平均年齢を出してみます。
In [42]: pd.pivot_table(df,values="Age",index="Cabin",columns="Embarked")
Out[42]:
Embarked C Q S
Cabin
A10 36.0 NaN NaN
A16 48.0 NaN NaN
A20 49.0 NaN NaN
A23 NaN NaN 80.000000
A24 NaN NaN 31.000000
A26 56.0 NaN NaN
... ... .. ...
E77 NaN NaN 57.000000
E8 NaN NaN 30.000000
F G63 NaN NaN 42.000000
F G73 NaN NaN 22.000000
F2 NaN NaN 13.833333
F33 NaN NaN 29.000000
F4 NaN NaN 2.500000
G6 NaN NaN 14.750000
T NaN NaN 45.000000
[133 rows x 3 columns]
欠損値が目立っているのがわかると思います。ここの値を0で埋めてみます。
fill_value=0
で可能です。
In [44]: pd.pivot_table(df,values="Age",index="Cabin",columns="Embarked",fill_value=0)
Out[44]:
Embarked C Q S
Cabin
A10 36.0 0.0 0.000000
A16 48.0 0.0 0.000000
A20 49.0 0.0 0.000000
A23 0.0 0.0 80.000000
A24 0.0 0.0 31.000000
A26 56.0 0.0 0.000000
... ... ... ...
E77 0.0 0.0 57.000000
E8 0.0 0.0 30.000000
F G63 0.0 0.0 42.000000
F G73 0.0 0.0 22.000000
F2 0.0 0.0 13.833333
F33 0.0 0.0 29.000000
F4 0.0 0.0 2.500000
G6 0.0 0.0 14.750000
T 0.0 0.0 45.000000
[133 rows x 3 columns]
欠損値があるデータも表示させる
デフォルトではdropna=True
となっており全ての全ての行(列)において欠損値である列(行)データは表示されません。
dorpna=False
にするとその設定を解除できます。
In [45]: pd.pivot_table(df,values="Age",index="Cabin",columns="Embarked",dropna=False)
Out[45]:
Embarked C Q S
Cabin
A10 36.0 NaN NaN
A14 NaN NaN NaN
A16 48.0 NaN NaN
A19 NaN NaN NaN
A20 49.0 NaN NaN
A23 NaN NaN 80.000000
A24 NaN NaN 31.000000
A26 56.0 NaN NaN
... ... .. ...
E77 NaN NaN 57.000000
E8 NaN NaN 30.000000
F E69 NaN NaN NaN
F G63 NaN NaN 42.000000
F G73 NaN NaN 22.000000
F2 NaN NaN 13.833333
F33 NaN NaN 29.000000
F38 NaN NaN NaN
F4 NaN NaN 2.500000
G6 NaN NaN 14.750000
T NaN NaN 45.000000
[146 rows x 3 columns]
形状をみてみると行数が増加していることがわかります。
In [48]: pd.pivot_table(df,values="Age",index="Cabin",columns="Embarked",dropna=False).shape
Out[48]: (146, 3)
In [49]: pd.pivot_table(df,values="Age",index="Cabin",columns="Embarked").shape
Out[49]: (133, 3)
まとめ
今回はpivot_table
関数の使い方について解説しました。ピボットテーブルはデータの見通しを良くする上で非常に強力な表となってきます。
agg_func
の指定の仕方で様々な数値データを呼び出すことが可能になるので、より使いこなしたい方はこの引数を使いこなせるように練習するとよいでしょう。