Pandas Groupbyの練習 (チートシート?)
Pandasを使っているとGroupbyな処理をしたくなることが増えてきます。ドキュメントを読んだりしながらよく使ったりする機能の骨格をまとめました。手っ取り早く勉強するなら、本が簡単そうです。

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理
- 作者: Wes McKinney,小林儀匡,鈴木宏尚,瀬戸山雅人,滝口開資,野上大介
- 出版社/メーカー: オライリージャパン
- 発売日: 2013/12/26
- メディア: 大型本
- この商品を含むブログ (19件) を見る
では、さっそくスタート。
pandasライブラリなどなどの読み込み
普段使っている感じのものをコピペ。matplotlibはinlineの方が好き。
%matplotlib inline # %matplotlib notebook import sqlite3 import pandas as pd from matplotlib import pylab as plt import numpy as np from datetime import datetime import dateutil
csvからpandasへのデータの読み込み
Climate Data Onlineから引っ張ってきた2016年1月の東京と京都に関する気象データをちょっと加工したものを使用。アメリカが出典なだけあって、単位がアメリカ風味。
df = pd.read_csv('./201601.csv',encoding="SHIFT-JIS") df.head()
Station | YEARMODA | TEMP | MAXT | MINT | WDSP | MXSPD | |
---|---|---|---|---|---|---|---|
0 | Tokyo | 20160101 | 45.1 | 53.8 | 37.2* | 4.9 | 9.9 |
1 | Tokyo | 20160102 | 45.3 | 56.1 | 36.7 | 2.5 | 6.0 |
2 | Tokyo | 20160103 | 49.6 | 61.2 | 37.4 | 3.0 | 5.1 |
3 | Tokyo | 20160104 | 49.9 | 59.4 | 39.9 | 3.4 | 6.0 |
4 | Tokyo | 20160105 | 51.5 | 59.7 | 41.2 | 3.3 | 5.1 |
- Station : 観測地点。今回は東京か京都。
- YEARMODA : YYYYMMDDフォーマットの年月日データ
- TEMP : 1日の平均気温。単位 華氏[℉]
- MAXT : 1日の最高気温。単位 華氏[℉] *印付きには事情があるのだが、今はゴミ。
- MINT : 1日の最低気温。単位 華氏[℉] *印付きは事情があるのだが、今はゴミ。
- WDSP : 1日の平均風速。単位 1/10ノット
- MXSP : 1日の最大風速。単位 1/10ノット
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 60 entries, 0 to 59
Data columns (total 7 columns):
Station 60 non-null object
YEARMODA 60 non-null int64
TEMP 60 non-null float64
MAXT 60 non-null object
MINT 60 non-null object
WDSP 60 non-null float64
MXSPD 60 non-null float64
dtypes: float64(3), int64(1), object(3)
memory usage: 3.4+ KB
pandasでのdatetime型への変換; 文字列→浮動小数点変換
ちょっとした前処理をします。MAXT, MINTがたまに入っている*のせいでobject扱いに。floatに直そう。ついでにYEARMODAも変換。
# YEARMODAをdatetime型にパース df['YEARMODA'] = df['YEARMODA'].apply(lambda x: dateutil.parser.parse(str(x))) # *を除去してfloat型に。 df['MAXT'] = df['MAXT'].apply(lambda x: float(str.replace(x, '*', ''))) df['MINT'] = df['MINT'].apply(lambda x: float(str.replace(x, '*', ''))) df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 60 entries, 0 to 59
Data columns (total 7 columns):
Station 60 non-null object
YEARMODA 60 non-null datetime64[ns]
TEMP 60 non-null float64
MAXT 60 non-null float64
MINT 60 non-null float64
WDSP 60 non-null float64
MXSPD 60 non-null float64
dtypes: datetime64[ns](1), float64(5), object(1)
memory usage: 3.4+ KB
df.head()
Station | YEARMODA | TEMP | MAXT | MINT | WDSP | MXSPD | |
---|---|---|---|---|---|---|---|
0 | Tokyo | 2016-01-01 | 45.1 | 53.8 | 37.2 | 4.9 | 9.9 |
1 | Tokyo | 2016-01-02 | 45.3 | 56.1 | 36.7 | 2.5 | 6.0 |
2 | Tokyo | 2016-01-03 | 49.6 | 61.2 | 37.4 | 3.0 | 5.1 |
3 | Tokyo | 2016-01-04 | 49.9 | 59.4 | 39.9 | 3.4 | 6.0 |
4 | Tokyo | 2016-01-05 | 51.5 | 59.7 | 41.2 | 3.3 | 5.1 |
Pandasの行方向計算
華氏から摂氏への変換
[C] = ([F] − 32) * 5/ 9で変換
df["TEMP"] = (df["TEMP"]-32)*5/9 df["MAXT"] = (df["MAXT"]-32)*5/9 df["MINT"] = (df["MINT"]-32)*5/9
風速:0.1ノットからm/sへの変換
0.1 ノット = 0.0514444[m/s]だそうです
df["WDSP"] *= 0.051444 df["MXSPD"] *= 0.051444
df.head()
Station | YEARMODA | TEMP | MAXT | MINT | WDSP | MXSPD | |
---|---|---|---|---|---|---|---|
0 | Tokyo | 2016-01-01 | 7.277778 | 12.111111 | 2.888889 | 0.252076 | 0.509296 |
1 | Tokyo | 2016-01-02 | 7.388889 | 13.388889 | 2.611111 | 0.128610 | 0.308664 |
2 | Tokyo | 2016-01-03 | 9.777778 | 16.222222 | 3.000000 | 0.154332 | 0.262364 |
3 | Tokyo | 2016-01-04 | 9.944444 | 15.222222 | 4.388889 | 0.174910 | 0.308664 |
4 | Tokyo | 2016-01-05 | 10.833333 | 15.388889 | 5.111111 | 0.169765 | 0.262364 |
groupbyとグループ毎での統計量
観測地点ごとにグルーピングして統計情報を出力をする練習。東京、京都それぞれの2016年1月の平均気温の平均、2016年1月の最高気温・最低気温を出してみましょう。
個別に出力する
統計量を個別に出力する場合です。あとでまとめて出す方法やります。
平均気温の平均
df.groupby("Station")["TEMP"].mean()
Station
Kyoto 5.881226
Tokyo 6.035842
Name: TEMP, dtype: float64
最高気温
df.groupby("Station")["MAXT"].max()
Station
Kyoto 16.000000
Tokyo 16.222222
Name: MAXT, dtype: float64
最低気温
df.groupby("Station")["MINT"].min()
Station
Kyoto -4.111111
Tokyo -2.611111
Name: MINT, dtype: float64
参考:Pandas組み込みのGroup用統計関数
上で使った基本的なもの以外にも、Essential Basic Functionality — pandas 0.19.2 documentationにある通り、いろいろな関数が組み込まれています。抜粋して翻訳。
関数 | 機能 |
---|---|
count | Non-Nullなデータの数 |
sum | 合計値 |
mean | 平均値 |
mad | 平均絶対偏差 |
median | メジアン(中央値)を出力 |
min | 最小値 |
max | 最大値 |
mode | モード(最頻値) |
abs | 絶対値 |
prod | 総乗 |
std | 標準偏差. 自由度を引数にとれるがデフォルトは1. |
var | 不偏分散 |
sem | 平均値の標準誤差(cf : 推計統計学) |
skew | 歪度 |
kurt | 尖度 |
quantile | 分位数またはクォンタイル。デフォルトでは中央値を出力する。 .quantile(.25)で25パーセンタイルを出力。 [参考]pandas.quantile — pandas |
cumsum | 累積和を出力(デフォルトで行方向) |
cumprod | 累積乗を出力 (デフォルトで行方向) |
cummax | 累積最大値。axis指定が必要。 |
cummin | 累積最小値。累積最大値と似てる。 |
まとめて出力する
個別に統計量を出力させてもよいのですが、まとめてバッっと出したい場合は。.agg関数を使うと素敵になる。
aggregations = { 'TEMP': { '1月の平均気温の平均': 'mean' }, 'MAXT': { '1月の最高気温' : 'max' }, 'MINT': { '1月の最低気温' : 'min' } } df.groupby("Station").agg(aggregations)
TEMP | MAXT | MINT | |
---|---|---|---|
1月の平均気温の平均 | 1月の最高気温 | 1月の最低気温 | |
Station | |||
Kyoto | 5.881226 | 16.000000 | -4.111111 |
Tokyo | 6.035842 | 16.222222 | -2.611111 |
Groupbyとmatplotlib
Pandasでグループ毎に分けてプロットする方法。連続してプロットすると重ね描きになるのはmatplotlibと同様。
cmap = plt.get_cmap('rainbow') fig, ax = plt.subplots() #df['YEARMODA'] = df.YEARMODA.astype(np.int64) for i, (key, group) in enumerate(df.groupby(['Station']), start=1): ax = group.plot(ax=ax, x='YEARMODA', y='TEMP',color=cmap(i / 4.0),label = key+"_avg") for i, (key, group) in enumerate(df.groupby(['Station']), start=1): ax = group.plot(ax=ax, x='YEARMODA', y='MAXT',color=cmap(2*(i+1) / 4.0),label = key+"_max") plt.title(u"2016/01 Temp") fig.patch.set_facecolor('white') plt.show()
Groupレベルの処理をDataFrameに戻す
Group別の処理結果を使って、元のデータを処理したい時のお話。
DataFrameにGroup別最大値を追加
DataFrameに、観測地別2016年1月最高気温をMAXT_Monthという列名で追加
df['MAXT_Month'] = df.loc[df.groupby('Station')['MAXT'].transform('idxmax'), 'MAXT'].values ## 別の方法 # df = df.join(df.groupby('Station')['MAXT'].max(), on='Station', rsuffix='_Month') df.head()
Station | YEARMODA | TEMP | MAXT | MINT | WDSP | MXSPD | MAXT_Month | |
---|---|---|---|---|---|---|---|---|
0 | Tokyo | 2016-01-01 | 7.277778 | 12.111111 | 2.888889 | 0.252076 | 0.509296 | 16.222222 |
1 | Tokyo | 2016-01-02 | 7.388889 | 13.388889 | 2.611111 | 0.128610 | 0.308664 | 16.222222 |
2 | Tokyo | 2016-01-03 | 9.777778 | 16.222222 | 3.000000 | 0.154332 | 0.262364 | 16.222222 |
3 | Tokyo | 2016-01-04 | 9.944444 | 15.222222 | 4.388889 | 0.174910 | 0.308664 | 16.222222 |
4 | Tokyo | 2016-01-05 | 10.833333 | 15.388889 | 5.111111 | 0.169765 | 0.262364 | 16.222222 |
Group別に他の列の条件に応じて代入値を決める
例えば、観測地別2016年1月 最高気温日の最大風速をMXSPD_of_DAY_MAXTという列名で追加
df['MXSPD_of_DAY_MAXT'] = df.loc[df.groupby('Station')['MAXT'].transform('idxmax'), 'MXSPD'].values df.head()
Station | YEARMODA | TEMP | MAXT | MINT | WDSP | MXSPD | MAXT_Month | MXSPD_of_DAY_MAXT | |
---|---|---|---|---|---|---|---|---|---|
0 | Tokyo | 2016-01-01 | 7.277778 | 12.111111 | 2.888889 | 0.252076 | 0.509296 | 16.222222 | 0.262364 |
1 | Tokyo | 2016-01-02 | 7.388889 | 13.388889 | 2.611111 | 0.128610 | 0.308664 | 16.222222 | 0.262364 |
2 | Tokyo | 2016-01-03 | 9.777778 | 16.222222 | 3.000000 | 0.154332 | 0.262364 | 16.222222 | 0.262364 |
3 | Tokyo | 2016-01-04 | 9.944444 | 15.222222 | 4.388889 | 0.174910 | 0.308664 | 16.222222 | 0.262364 |
4 | Tokyo | 2016-01-05 | 10.833333 | 15.388889 | 5.111111 | 0.169765 | 0.262364 | 16.222222 | 0.262364 |