pandasのDataFrame にはデータを集計するためのgroupby や resampleというメソッドが用意されています。
個々の使い方については他のサイトで解説されていますが、体系的に解説している記事が見つからなかったので、今回はこれを取り上げました。
図を使って説明していますので、興味のあるかたは是非ご一読下さい。
pandasを使った集計の概要
pandasのDataFrameに格納されているデータに対して、groupby や resample というメソッドを使うとことで、グルーピング集計が可能です。
groupby メソッドは任意の数値型、文字列型のカラムに対して集計するのに対し、resample は時系列データに対しての集計を行います。
これらグループ化メソッドを使うとオブジェクトが生成されますので、そのオブジェクトにある集計メソッドを呼び出すことで集計結果を受取ることが出来ます。

集計結果は DataFrame として返って来ますが、階層型インデックス(MultiIndex)になっているため、値の取り出し方には少しだけ注意が必要です。

集計結果から値を取り出すには、通常通り添え字にカラム名と行番号を指定すれば良いのですが、インデックスとなっている元のカラム名は指定できません。
下図は売上年月日と商品名で構成されたMultiIndexの例です。
MultiIndexは1つ以上のカラム名がタプルで構成されており、index[行番号] で取得することが可能です。

このアクセス方法が面倒な場合は、reset_index メソッドを使ってMultiIndexを解除すれば通常のDataFrameと同じアクセスができるようになります。
df.reset_index()
という1行を実行するだけで解除可能です。
groupby を使った集計
groupby によるグループ化は引数に1つ以上のカラム名を指定します。
df.groupby(カラム名)
複数のカラム名で階層的にグループ化したい場合、リストでカラム名を複数指定します。
SQL の group by カラム1,カラム2,・・・と同じ考え方です。

グループ化した結果は DataFrameGroupByオブジェクトとして返されますので、続けて集計メソッドを呼び出します。
集計メソッドは数多く用意されており、欠損値の補間なども可能なのですが、ここでは良くつ分かれる集計メソッドのみ一覧にしました。
詳細な情報が必要な場合は、pandas公式ドキュメントをご参照ください。
尚、下記メソッドは欠損値を除いた値を集計対象としています。
メソッド名 | 内容 |
---|---|
mean | 平均 |
sum | 合計 |
max | 最大 |
min | 最小 |
median | 中央値 |
std | 標準偏差 |
var | 分散 |
count | 各グループの行数 |
では、具体的な例を挙げてみます。
下記はサンプルデータなので、この記事に掲載したプログラムを実際に動かしたい場合、メモ帳等でCSVファイルとして保存してお使いください。
1 2 3 4 5 6 7 8 9 10 11 |
売上年月日,商品名,単価,数量 2021-7-1,ケーキ,200,5 2021-7-1,ケーキ,200,3 2021-7-2,ケーキ,200,1 2021-7-2,ケーキ,150,2 2021-7-2,バナナ,100,5 2021-7-2,プリン,150,4 2021-7-3,バナナ,100,5 2021-7-3,プリン,150,6 2021-7-3,バナナ,100,5 2021-7-3,ケーキ,200,2 |
p:ドライブに group_data.csv という名前のCSVがあり、上記データが格納されているという前提で、商品名でグループ化し、それぞれの合計を計算する場合、次の様になります。
1 2 3 4 5 |
import pandas as pd df = pd.read_csv('p:/group_data.csv',encoding='shift-jis',sep=',') df.groupby('商品名').sum() |

商品名だけで集計しているため、インデックス以外のカラム(単価と数量)はそれぞれ合計値が計算されます。

次は、売上年月日と商品名でグループ化してみます。
1 2 3 4 |
import pandas as pd df = pd.read_csv('p:/group_data.csv',encoding='shift-jis',sep=',') df.groupby(['売上年月日','商品名']).sum() |

売上年月日と商品名が index となっていることが分かると思います。
グルーピング集計した結果の行数(=インデックスの個数)を取得する場合は、 size プロパティを使います。
df.index.size
1 2 3 4 5 6 7 8 9 10 11 12 |
import pandas as pd df = pd.read_csv('p:/group_data.csv',encoding='shift-jis',sep=',') res = df.groupby(['売上年月日','商品名']).sum() #sizeで取得したインデックス個数を使ったループ for i in range(res.index.size): print(res.index[i]) #indexを使ったループ for i in res.index: print(i) |
resampleを使った集計
resample は時系列に特化したグルーピング集計です。
resample の引数には集計期間を示す文字を指定します。
df.resample(集計期間)

集計期間には次の文字が指定できます。
また、文字の前に数値を書くことで、2日や3ヶ月といった指定も可能です。
集計期間 | 文字 | 使用例 |
---|---|---|
日 | D | resample(‘2D’) ⇒2日ごとの集計 |
週 | W | resample(‘3W’) ⇒3週間ごとの集計 |
月 | M | resample(‘M’) ⇒1か月ごとの集計 |
四半期 | Q | resample(‘Q’) ⇒四半期ごとの集計 |
年 | Y | resample(‘5Y’) ⇒5年ごとの集計 |
先ほどの例では、売上年月日を扱いましたが、あれは文字列として取り扱っていました。
resample で集計を行うには、インデックスが datetime型である必要があります。
read_csv で指定したカラムをdatetime型のインデックスとして取り込むためには、index_col 引数とparse_dates 引数を指定します。
pd.read_dsv(ファイル名,index_col=カラム番号,parse_dates=True)
先ほどのCSVを例に、売上年月日をdatetime型のインデックスとして指定し、月ごとの集計を行うには次の様になります。
1 2 3 4 |
import pandas as pd df = pd.read_csv('p:/group_data.csv',encoding='shift-jis',sep=',',index_col=0,parse_dates=True) df.resample('M').sum() |

今回のサンプルデータは7月のデータしかないので、1か月ごとの集計では1行となります。

まとめ
今回はpandas DataFrame を使った集計について、groupby と resample を紹介いたしました。
単に月ごとや年毎であれば、文字列として扱って groupby すれば事足りますが、2日ごとや1週間ごとなどの集計では resample を使う方が圧倒的に便利です。
resample は datetime 型のインデックスで集計するため、もちろん1時間ごとや5分毎、秒単位での集計も可能です。
CSVデータをサクっと集計するには非常に便利ですが、慣れない間はけっこう悩んでしまうのではないでしょうか。
そんな方のために、今回の記事がお役に立てれば幸いです。