Pandasのgroupbyメソッドについて
Pandasにはグループ演算する仕組みのgroupbyメソッドが用意されています。
グループ演算とは、分離、適用、結合を行うものです。従ってgroupbyメソッドを使う場合も、分離、適用、結合の作業が必要です。
- データフレーム型のデータから、特定の列か行の値をキーとする
- 指定したキーで分離をする
- 分離したグループそれぞれに関数を適用
- 適用した関数を実行した結果が結合される
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動画で使用したものです。
コメントを投稿するにはログインしてください。