Pandasの活用 groupbyメソッドの使い方(動画あり)

lecture
Pandas活用 GroupByの使い方
スポンサーリンク

Pandasのgroupbyメソッドについて

Pandasにはグループ演算する仕組みのgroupbyメソッドが用意されています。

グループ演算とは、分離、適用、結合を行うものです。従ってgroupbyメソッドを使う場合も、分離、適用、結合の作業が必要です。

  1. データフレーム型のデータから、特定の列か行の値をキーとする
  2. 指定したキーで分離をする
  3. 分離したグループそれぞれに関数を適用
  4. 適用した関数を実行した結果が結合される

GroupByメソッドで返される値は、2番目の措定したキーで分離された値が、イテレータ の状態で返されます。
そのため、3以降の内容は自分で何らかの処置を決める必要があります。

簡単にイラストにすると次のような図で表すことができます。

グループ化

groupbyメソッドのキーを指定する方法

データをグループ化する場合、何を基準にグループ化するのかという「キー」を決める必要があります。
groupbyメソッドのキーは次のような方法で指定できます。

  • リストや配列にしたキー
  • データフレームの列名を示す値
  • ディクショナリかシリーズ形式のもの
  • 軸のインデックスまたはそれに対応した関数

分離したグループそれぞれに関数を適用

データ集約するためのGropByの最適化されたメソッドには次のものがあります。

  • count:グループ内の欠損値以外の値の数
  • sum:欠損値以外の合計
  • mean:欠損値以外の平均
  • median:欠損値以外の中央値
  • std:標準偏差
  • var:分散
  • min:最小値
  • max:最大値
  • prod:欠損値以外の積
  • first:欠損値以外の最初
  • last:欠損値以外の最後

これ以外にも自分で定義した関数を使うこともできます。

実例

次に、具体的にサンプルコードで確認してみます。
5人の数学と英語の点数をデータフレーム型にしたデータを用意して、科目別並びに男女別にグループ化します。

データフレーム作成コード

import pandas as pd
import numpy as np

df = pd.DataFrame({'名前':['磯野','中島','花澤','フグ田','伊佐坂'],
                   '性別':['男','男','女','女','男'],
                   '数学':np.random.randint(50,90,5),
                   '英語':np.random.randint(50,90,5)})
df

結果

名前 性別 数学 英語
0 磯野 58 83
1 中島 77 72
2 花澤 53 67
3 フグ田 87 67
4 伊佐坂 67 81

groupbyメソッドのキーをSeriesで指定する方法

性別でグループ化

キーは性別の列(Series)にします。

数学と英語それぞれ、性別でグループ化するコード

grouped_math = df['数学'].groupby(df['性別'])
grouped_en = df['英語'].groupby(df['性別'])
print('数学:',grouped_math.mean())
print('------------------------')
print('英語:',grouped_en.mean())

結果
数学: 性別
女 70.000000
男 67.333333
Name: 数学, dtype: float64
————————
英語: 性別
女 67.000000
男 78.666667
Name: 英語, dtype: float64

次にもう少し踏み込んでgroupbyメソッドの働きを確認します。
例として数学の成績を性別にグループ化して表示します。
まず、groupbyメソッドが返してきた値「grouped_math」をprintで確認すると「」オブジェクトの回答が返ってきて中身を確認できません。

次にfor in文でオブジェクトをイテレータ としてループさせて中のデータを取り出しています。

groupbyメソッドがイテレータ を返すことを確認するコード

grouped_math = df['数学'].groupby(df['性別'])
print(grouped_math)
print('----------------------')
for v in grouped_math:
  print(v)

結果 ———————-
(‘女’, 2 53
3 87
Name: 数学, dtype: int64)
(‘男’, 0 58
1 77
4 67
Name: 数学, dtype: int64)

科目の列を複数にしたい場合は、Pandasの複数列を指定する方法でリストで列を指定してすれば良いです。

複数列を性別でグループ化するコード

grouped = df[['数学','英語']].groupby(df['性別'])
grouped.mean()

結果

数学 英語
性別
70.000000 67.000000
67.333333 78.666667

複数のキーでグループ化したい場合は、groupbyメソッドの引数をリストで指定します。

複数キーでグループ化するコード

grouped = df[['数学','英語']].groupby([df['性別'],df['名前']])
grouped.mean()

結果

数学 英語
性別 名前
フグ田 87 67
花澤 53 67
中島 77 72
伊佐坂 67 81
磯野 58 83

groupbyのキーを列名で指定する方法

groupbyには列名を指定することもできます。
列名で指定する場合は、groupbyを指定するオブジェクトは、データフレーム型のオブジェクトを指定しておきます。この場合だとdfになります。
キーをSeriesで指定した場合は、それぞれグループ化したい列のデータを指定すれば良かったのですが、グループ化のキーを列名にする場合は、その列の情報を知っているオブジェクトを指定しないといけないのです。

groupbyのキーを列名で指定するコード

grouped = df.groupby('性別')
grouped.mean()

結果

数学 英語
性別
70.000000 67.000000
67.333333 78.666667

次の書き方はエラーになります。df[‘数学’]には「性別列」の情報が無いからです。

grouped = df['数学'].groupby('性別')

結果
エラー

複数の列をキーにしたい場合はリストで指定します。

複数の列を指定するコード

grouped = df.groupby(['性別','名前'])
grouped.mean()

結果

数学 英語
性別 名前
フグ田 87 67
花澤 53 67
中島 77 72
伊佐坂 67 81
磯野 58 83

リストでグループ化

行をグループ化するにはリストで指定する方法があります。

行の順番を入れ替えた例

grouped = df['数学'].groupby([2,1,3,5,4])
grouped.mean()

結果
1 77
2 58
3 53
4 67
5 87
Name: 数学, dtype: int64

行のグループ化の例
groupby([1,1,1,2,2])とすることで、index0からindex2までを1のグループ、index3からindex4までものを2のグループにしている。

grouped = df['数学'].groupby([1,1,1,2,2])
# print(list(grouped))
grouped.mean()

結果
1 62.666667
2 77.000000
Name: 数学, dtype: float64

groupedのキーの配列は文字列にすることもできます。
次の例の結果は上の例と同じになります。

文字列で行をグループ化

grouped = df['数学'].groupby(['a','a','a','b','b'])
# print(list(grouped))
grouped.mean()

結果
a 62.666667
b 77.000000
Name: 数学, dtype: float64

ディクショナリやSeriesでマッピングしてグループ化

辞書でマッピングを作成しておくとその辞書をキーに使えます。
例えば、語学というグループは英語と国語とドイツ語として、科学というグループは物理、化学、数学としたい時などに使えます。

サンプル用データフレーム作成コード

record = pd.DataFrame(np.random.randint(30,80,25).reshape(5,5),
                      columns=['Japanese','Physics','English','German','Chemistry'],
                      index=['Isono','Fuguta','Nakajima','Hanazawa','Isasaka'])
record

結果

Japanese Physics English German Chemistry
Isono 46 36 31 37 37
Fuguta 70 72 53 54 45
Nakajima 49 34 51 74 38
Hanazawa 31 74 78 37 44
Isasaka 60 52 79 48 55

マッピング用の辞書を作成コード

mapping = {'Japanese':'Language','Physics':'Science','English':'Language','German':'Language','Chemistry':'Science'}

辞書でグループ化

record_g = record.groupby(mapping, axis=1)
record_g.mean()

結果

Language Science
Isono 38.000000 36.5
Fuguta 59.000000 58.5
Nakajima 58.000000 36.0
Hanazawa 48.666667 59.0
Isasaka 62.333333 53.5

辞書をSeries化してマッピング

Seriesでもマッピングできます。(辞書と同様になる)

mapping_s = pd.Series(mapping)
record_gs = record.groupby(mapping_s, axis=1)
record_gs.mean()

結果

Language Science
Isono 38.000000 36.5
Fuguta 59.000000 58.5
Nakajima 58.000000 36.0
Hanazawa 48.666667 59.0
Isasaka 62.333333 53.5

参考になった書籍

Pandasを使いこなすための必携の本。Pandasの作者自ら書いた本でNumpyやPandasの使い方が詳細に書かれている。

今回使用したサンプルもこの本のGroupByの項目をもとに説明しています。

Pythonサンプルのダウンロード

ここでダウンロードする「groupby.ipynb」ファイルは、このPandas動画で使用したものです。

groupby.ipynb

タイトルとURLをコピーしました