最終更新日:2021/8/21

.groupby()を使って、dfを特定の条件でグループ化して計算する方法を説明します。
例えば、各データがA, B, Cの何れかの値を必ず持っている場合、A, B, Cというくくりでグループ分けし、それぞれの合計を計算します。

【説明すること】

1. 簡単な計算

1つのカラムが対象の場合

和、平均、最小値、最大値など、簡単な計算は、関数が用意されているので、df.groupby()を使って、
df.groupby(['clm0']).sum()['clm2']
と書きます。
この例は、’clm0’でグループ化し、’clm2’の和を集計する、という意味です。(対象が違う。)

複数のカラムが対象の場合

複数のカラムでグループ化したい場合は.goupby()の引数にリストでカラム名を指定して、
df.groupby(['clm0','clm1']).sum()['clm2']
と書きます。
この例は、’clm0’を第一優先、’clm1’を第二優先でグループ化し、’clm2’の和を集計する、という意味です。

代表的な関数

代表的な関数は以下の通りです。

.sum() : 和
.mean() : 平均
.min() : 最小値
.max() : 最大値
.prod() : 積(ExcelのPORDUCT())
.var(ddof=k) : 分散 (ddofは不偏分散ならばk=1を指定します。つまり分母。)
.std(ddof=k) : 標準偏差(ddofは不偏分散ならばk=1を指定します。つまり分母。)

更に関数を知りたい場合は、以下のpandasのページを参照してください(英語)
https://pandas.pydata.org/pandas-docs/stable/reference/groupby.html

サンプルコード

以下のcsvファイルを読み込んで例を挙げます。

a004_008a.csv

【1つのカラムが対象の場合】


【複数のカラムが対象の場合】


【株価データの例】

以下のcsvファイルを読み込んで例を挙げます。

a004_008b.csv

2. ラムダ関数を使った少し複雑な計算

少し複雑な計算は、.apply(lambda x: f(x))で、ラムダ関数を使用して実行することができます。
例えば、(価格)×(数量)=(合計金額)を集計したい場合は、以下のように書きます。
df.groupby(['city','item']).apply(lambda x: (x['price'] * x['qty']).sum())

【合計金額の例】

【株価の例】

3. 一気に計算する場合

.agg()を使えば、全てのカラムに対してまとめて計算することができます。
例えば、clm0, clm1をグループ化して、それらグループごとの和を集計したい場合は、以下のように書きます。
df.groupby(['clm0','clm1']).agg(['sum'])

ここで注意が必要なのが関数の指定方法です。
大きく分けて2つの方法があります。

(1) 組み込み関数を使う

この場合、ライブラリーをimportする必要はありません。
普通に関数の名前を書くだけです。但し、カッコ「()」は付きません。
例えば、和の場合、’sum’と書きます(”でくくる。カッコなし)。
「sum()」でも「sum」(”がない)でもありません。

(2) numpyを使う

numpyという数学計算用のライブラリーを使う場合は、numpyをimportして、np.cumprodのようにカッコを付けないで書きます。
コードは、最初にimport numpy as npと書くのを忘れないでください。

よく使うnumpyの関数は以下の通りです。

関数 計算の内容
np.sum 総和
np.prod 総乗
np.cumsum累積和
np.cumprod 累積積
np.nansum 総和 (欠損値は1として計算実行)
np.nanprod 総乗 (欠損値は1として計算実行)
np.nancumsum 累積和 (欠損値は1として計算実行)
np.nancumprod 累積積 (欠損値は1として計算実行)

更に詳しく知りたい場合は、以下のpandasのサイトを参考にしてくだい(英語)。
https://pandas.pydata.org/pandas-docs/version/0.23/generated/pandas.core.groupby.DataFrameGroupBy.agg.html

numpyの例

numpyの関数を使ったコードの例を挙げます。


更に、以下のcsvファイルを読み込み、numpyの各関数の例を示します。

a004_008c.csv

4. 結果をcsvに出力する

.groupby()で計算した結果をcsvに出力したい事もあるでしょう。
例えば、データの数が多く、コードの正しさを検証する場合が考えられます。

この場合、結果を入れたdf_resultに対して、df_result.to_csv()だけではうまくいきません。
以下のように、df.groupby()のオプションでas_index = Falseを指定すれば、出力が可能です。

df_new = df.groupby(['clm0', 'clm1], as_index = False).sum()['clm2']

この理由は、後述する.groupby()の出力のイメージ図をご覧頂くと、納得がいくはずです。


【csvに出力できない理由】

as_index = Falseを指定しない場合、以下のようにcityカラムがExcelでいうセルの結合のようになっています。これでは、dfに必須のindex番号を振りようにも振れません。
結合したセルにデータを入力しても、1行でカウントされる状態です。

city

item

qty

Nagoya

apple

50

banana

20

grape

30

Osaka

apple

100

banana

600

grape

300

Tokyo

apple

1000

banana

2000

grape

7000

as_index = Falseを指定すると、Excelでいうセルの結合が解除され、1行ずつに分類されます。これで、index番号が振れるようになるわけです。

indexcityitemqty
0Naogyaapple50
1 Naogya banana20
2 Naogya grape30
3Osaka apple 100
4 Osaka banana 600
5 Osaka grape 300
6Tokyo apple 1000
7 Tokyo banana 2000
8 Tokyo grape 7000

これはあくまでイメージですが、基本的にデータは、1行ずつ完結する形になっていなければならない訳です。