Pandas入門講座|09.データ集計(groupby)の方法【PythonのライブラリPandas】

はじめに

こんにちは。キノコードです。
この動画では、データを集計する方法について学びます。
具体的には、売上管理表を使って部署や名前ごとで売上げや平均を集計をするといった方法をみていきます。
Excelでいうと、Sum関数、sumifs関数、countifs関数、SQLでいうとGroupbyの方法になります。
Pythonでは集計方法をカスタマイズすることが可能です。そのため、その会社独自の集計方法や、特殊な集計をすることが可能です。
SQLやエクセルではできないことも可能なので、ぜひ最後までご視聴ください。
読み込む前の準備として概要欄に記載したキノコードのサイトにExcelファイルを用意しています。
それをダウンロードして、学習用のJupyter Labを保存しているフォルダにに保存してください。
それではパソコン画面に切り替えてレッスンを進めていきましょう。

Pandasインポート

import pandas as pd

それでは、Pandasをインポートするところから始めていきましょう。
まず、Pandasをインポートする記述を書きます。
「import pandas as pd」を書きます。
「as」は、ライブラリ名(pandas)を好きな名前で使うことができます。
したがって、この記述により「pandas」を「pd」という名前で使うことができます。
エラーにならず、インポートが完了しました。

表示する列数・行数を変更

pd.set_option(‘display.max_columns’, None) # 最大表示列数
pd.set_option(‘display.max_rows’, 5) # 最大表示行数

次に、表示する列数・行数を変更します。
レッスン03で表示する列数・行数を変更はset_opitonでやってきました。
今回は、pd.options.displayで変更をしてみましょう。
pd.options.displayと書いてmax_rowと書きます。そして、これに10を代入します。
これで表示する行数を10行に変更することができます。
次に、表示する列数の変更をします。
max_columnsと書いて、Noneを代入します。
これで表示する列数・行数を変更ができました。

データフレームの読み込み

df = pd.read_excel(‘sample.xlsx’,sheet_name=’実績管理表’)
df

続いてレッスンで使うデータを説明します。
今回はエクセルデータを使います。
このデータはあるアパレル会社の販売データになります。
社員ごとに何をいくら売上したのかがわかります。
エクセルを読み取るにはread_excelメソッドを使いました。
これはレッスン6で説明しました。
そこでは説明していなかったのですが、エクセルのシートを指定して読み取ることができます。
heet_nameという引数にシート名を渡せばよいです。
実行してみましょう。
読み取れました。

氏名ごとの集計

df.groupby(‘氏名’)

それでは氏名ごとに合計や平均など色々な集計をしてみましょう。
エクセルでいうとsumifs関数であったり、averageifs関数、countifs関数になります。
SQLでいうとGroupbyです。
Pythonの場合だと、PandasのGroupbyメソッドを使います。
データフレームが代入されている変数のあとにドット、groupby、丸括弧。
丸括弧の中に、集計したいグループを記述します。
氏名ごとに集計をしたいので、氏名を記述します。

実行してみましょう。
集計結果が返ってきません。
これはオブジェクト生成されただけで、このオブジェクトに対して何も処理をしていないからです。

平均を算出

df.groupby(‘氏名’).mean()

このgroupbyメソッドに平均を求めならmean、合計を求めるならsumなどを追加することで集計することが可能です。
平均を求めてみましょう。
平均は、meanを使います。
実行します。
平均を集計することができました。
ただ、コードだと数値型のカラムがすべて平均になっていしまいました。

売上金額の平均

df[[‘氏名’,’売上金額’]].groupby(‘氏名’).mean()

売上金額だけ平均にしたい場合はどのようにしたらいいでしょうか?
その場合は、二重括弧で氏名と売上金額だけを抽出し、groupbyの丸括弧の中に氏名を記述します。列の取得の仕方はレッスン4で説明しています。
実行します。
売上金額だけ平均を算出することができました。
ただし、今の平均の算出方法だと小数点以下がたくさん表示されて読みにくいですよね。

小数点以下省略

pd.options.display.float_format = ‘{:.0f}’.format

そこで、小数点以下を表示させない設定に変更しましょう。
動画の最初で表示する行数や列数を設定しましたが、同じようにpd.options.displayを使います。float_formatと記述します。

これは小数点以下0桁を省略する記述です。
実行してみましょう。

df[[‘氏名’,’売上金額’]].groupby(‘氏名’).mean()

それではもう一度、実行してみましょう。
小数点以下が表示されず、すっきりなりました。

合計を算出

df[[‘氏名’,’売上金額’]].groupby(‘氏名’).sum()

合計を算出した場合は、sumです。
実行してみましょう。
合計が表示されました。

データ数を数える

df[[‘氏名’,’売上金額’]].groupby(‘氏名’).count()

データ数を数えたい場合はcountでできます
ただし、countメソッドだと、欠損値は数えてくれません。

データ数を数える(欠損値を含む)

df[[‘氏名’,’売上金額’]].groupby(‘氏名’).size()

欠損値も数えたい場合は、sizeメソッドを使います。
実行します。Seriesにて出力がされましたが、こうすれば欠損値も数えることができます。

n番目のデータ取得

df[[‘氏名’,’売上金額’]].groupby(‘氏名’).nth(5)

他にも、グループの中のn番目のデータを取得することもできます。例えば3番目だとか5番目のデータを取得するといったことができます。
n番目のデータを取得するには、nthメソッドでできます。
nthと書いて、丸括弧の中に取得したい番号を記述します。このnは、0から始まるので注意です。
5と書いて、それぞれの5番目のデータを取得してみましょう。
実行します。
5番目のデータを取得できました。

df[[‘氏名’,’売上金額’]].groupby(‘氏名’).nth(0)

例えば、0番目は欠損値です。
やってみましょう。
nanが返ってきて、欠損地であることがわかります。

最大値、最小値

df[[‘氏名’,’売上金額’]].groupby(‘氏名’).max()

最大値の場合はmaxを使います。

df[[‘氏名’,’売上金額’]].groupby(‘氏名’).min()

最小値の場合はminを使います。
他にも、中央値、標準偏差や分散を求めることができます。
便利なので、使ってみてください。

複数要素でグルーピング

df[[‘氏名’,’商品分類’,’売上金額’]].groupby([‘氏名’,’商品分類’]).mean()

次に、氏名の中でも商品分類ごとに集計したい場合をみていきましょう。
氏名と商品分類と売上金額のデータフレームにして、groupbyの丸括弧の中にグルーピングしたいカラム名をリストで渡します。
meanで平均を算出しましょう。
氏名と商品分類ごとの平均が算出されました。

df[[‘氏名’,’商品分類’,’売上金額’]].groupby([‘氏名’,’商品分類’],as_index=False).mean()

今までみてきたデータ集計方法だと、グループ化するカラムがインデックスになっていました。
前回のコードだとマルチインデックスになっていました。
それを回避したい場合は、groupbyのas_indexという引数にFalseを渡します。
そうすると、グループ化するカラムがインデックスになることはありません。
実行してみましょう。
グループ化するカラムがインデックスにならずに平均を算出することができました。

aggメソッド

df[[‘氏名’,’売上金額’]].groupby([‘氏名’]).mean()

次に、違う集計方法をやってみます。今までみてきた平均の出し方はこうでしたよね。

df[[‘氏名’,’売上金額’]].groupby([‘氏名’]).agg(‘mean’)

これと同じ書き方が、aggメソッドで算出することができます。
aggは、Aggregationの略です。
Aggregationは、集約するとは、凝縮するといった意味です。
実行してみましょう。
同じ平均が算出することができました。

df[[‘氏名’,’売上金額’]].groupby([‘氏名’]).agg([‘mean’,’sum’])

aggメソッドが便利なのは、平均や合計を同時に算出することができることです。
算出したい計算方法をaggの丸括弧の中にリストで渡してあげればよいです。
実行しましょう。
平均と合計を算出することができました。

桁区切り表示

df_group = df[[‘氏名’,’売上金額’]].groupby([‘氏名’]).agg([‘mean’,’sum’])
df_group.applymap(‘{:,.0f}’.format)

桁数が多くなってくると、数値がわかりにくいですね。
その場合は、3桁区切りをいれてあげましょう。
applymapとformatを使います。
applymatについては、このPandas入門コースで、format関数についてはPython入門コースでじっくり説明する予定です。
チャンネル登録をしてお待ち頂けましたら幸いです。
今はこのような書き方だと覚えてしまいましょう。
実行します。
3桁区切りが入って読みやすくなりました。

aggメソッド(複数計算)

df_group = df[[‘氏名’,’売上金額’]].groupby(‘氏名’).agg([‘mean’,’sum’,’count’,’max’,’min’,’std’,’var’])
df_group.applymap(‘{:,.0f}’.format)

aggメソッドの他の計算方法として、平均、合計、個数、最大値、最小値、標準偏差、分散などがあります。
実行してみましょう。
算出できました。

df_group = df[[‘氏名’,’売上金額’]].groupby(‘氏名’).agg([‘describe’])
df_group.applymap(‘{:,.0f}’.format)

グループごとの統計量を知りたいのであれば、レッスン3で説明したdescribeもよいでしょう。
実行します。
主要な統計量を一気に算出することができました。

自作の関数適用

def cal_tax(s):
return np.sum(s)*1.08

aggメソッドの計算では、自分で定義した関数を使うことができます。
そのため、複雑な計算であったり、お勤めの会社の独自の計算をすることもできます。
今回はシンプルに消費税込みの金額を算出してみましょう。
まず、税込みの計算のためにnumpyをインポートしましょう。
NumPyとは、高速にリストの計算をするためのライブラリです。このnumpyをnpという名前で使えるようにします。
関数の定義はdefでやります。
python超入門コース、レッスン12で関数の定義の方法をレクチャーしました。忘れた方は、復習で再度そちらをご覧ください。
今、右上にカードがでているはずです。
さて、関数の定義をしていきます。
まず、defと書いて、関数名を書きましょう。
今回は計算という意味のcalと税金のtaxで、cal_taxとします。
np.sumで合計を算出することができるので、これに対して1.10を掛け算します。
これをreturnで返しましょう。
この今定義したcal_taxの関数を使ってみましょう。

df[[‘氏名’,’売上金額’]].groupby(‘氏名’).agg({‘売上金額’: cal_tax})

aggの丸括弧の中に、辞書型の波括弧を書きます。
売上金額を集計するので売上金額を書きます。
コロンを書いて、定義したcal_taxを書きます。
実行してみましょう。
消費税が計算できました。

レッスンで使ったファイルはこちら

■保存方法
Mac:右クリック⇒「リンク先を別名で保存」
Windows:右クリック⇒「名前を付けてリンク先を保存」

Excelファイルはこちら

Jupyter Labのファイルはこちら