LoginSignup
3
2

More than 1 year has passed since last update.

groupby関数を使ってデータフレームを分割して処理する方法

Last updated at Posted at 2020-06-14

本記事について

Pythonのpandasを使ったデータ分析において、groupby関数はグループごとに演算してくれる便利な関数です。
私がよく利用するのは、
df.groupby(df['col1'])['col2'].mean() や .describe() 
といったオーソドックスな関数ですが、
「分割されたデータフレームごとに処理したい」ことがあり、
forget_groupを組み合わせるとだけで、都合よく処理できることが分かりましたので紹介します。

データの準備

groupby_get_group.py
import pandas as pd
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import numpy as np

iris_dataset = load_iris()
df_iris=pd.DataFrame(iris_dataset.data,columns=iris_dataset.feature_names)
#targetの列を追加
df_iris.loc[:,'target']=iris_dataset.target
#品種名のdictionaryを作成
iris_map=dict(zip([0,1,2],iris_dataset.target_names))
#DataFrameとdictionaryをmap関数でつなぎtarget_namesの列を追加
df_iris.loc[:,'target_names']=df_iris['target'].map(iris_map)

sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) target target_names
5.1 3.5 1.4 0.2 0 setosa
4.9 3.0 1.4 0.2 0 setosa
- - - - - -
5.7 2.8 4.1 1.3 1 versicolor
- - - - - -
6.3 3.3 6.0 2.5 2 virginica

target_namesにgroupby関数を適用してみる

品種('target_names')ごとにデータフレーム(df_iris)を分割します。
分割したものを gp としました。

groupby_get_group.py
gp = df_iris.groupby('target_names')

分割されたオブジェクトの属性を調べてみる

In[0]:type(gp)
Out[0]:pandas.core.groupby.generic.DataFrameGroupBy

In[1]:print(gp)
Out[1]:<pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000028788A33708>

groupbyを使って分割したデータセットをそのまま使うことはできません。
そこで、for文を使って属性などを調査してみます。

for文を使う

In[2]:for d_gp in gp:
          print(d_gp)
Out[2]:
 147                6.5               3.0  ...       2     virginica
 148                6.2               3.4  ...       2     virginica
 149                5.9               3.0  ...       2     virginica

 [50 rows x 6 columns])

In[3]:type(d_gp)
out[3]:tuple

分割されたデータフレームはタプル型変数(d_gp)として収納されているようです。
ここで、タプルの中身を確認するために、以下を打ち込んでみると、

In[4]:d_gp[0]
Out[4]:'virginica'

In[5]:d_gp[1]
Out[5]:
     sepal length (cm)  sepal width (cm)  ...  target  target_names
100                6.3               3.3  ...       2     virginica
101                5.8               2.7  ...       2     virginica
102                7.1               3.0  ...       2     virginica
103                6.3               2.9  ...       2     virginica

147                6.5               3.0  ...       2     virginica
148                6.2               3.4  ...       2     virginica
149                5.9               3.0  ...       2     virginica

[50 rows x 6 columns]

と書き出されるので、for文の実行後の状態は、"target_names"の3つ目の水準'virginica'のデータフレームが d_gp に代入されていることが確認できます。

したがって、d_gp[1]だけを繰り返し処理してもいいのですが、ここではd_gp[0]を活用して、get_group関数によってイテレータの性質をつかって、forループのみで特定のデータセットを取り出して処理していきます。

#get_groupによりタプルに収納されたデータを取り出す。

forループでデータフレームを抽出する

for文で取り出せるのは2つのタプルであり、
タプルの1つ目にはgroupbyにかけた列の水準(品種:setosa,versicolor,virginica)が収納され、
2つ目にはそれぞれのデータフレームが収納されています。

このタプルの1つ目に収納された水準を変数として、get_groupでタプルの2つ目に収納されたデータフレームを取り出して、水準毎に処理をしていきます。
これをそれぞれ取り出すのは、forループでforとinの間に2つの変数を用意してあげると、取り出すことができます。つまり、2つ目の変数が分割されたデータフレームです。

以下はsetosa,versicolor,virginicaの品種ごとに分割されたデータフレームを
品種を指定してデータフレームを取り出し、
「ガクの長さ(sepal length)」と「ガクの幅(sepal width)」をプロットしたもの。

groupby_get_group.py
#2021/8/12修正 forループでget_groupを使わない方法に修正
#以下でd_gp[0]はidxとなる
#for d_gp in gp:
#    df_g=gp.get_group(d_gp[0])
for idx,df_g in gp:
    ##ここ以下に分割したデータフレームを使って処理したいことを書く
    fig = plt.figure()
    ax = fig.add_subplot(1,1,1)
    X=df_g[df_g.columns[0]].values
    y=df_g[df_g.columns[1]].values
    #ax.set_title(str.capitalize(d_gp[0])+"  "+\
    ax.set_title(str.capitalize(idx+"  "+\
                 str.capitalize(df_g.columns[0])+\
                 ' vs '+str.capitalize(df_g.columns[1]))
    ax.scatter(X,y,marker='o',color='darkblue',edgecolor="")
    cor=np.corrcoef(X, y)[0,1]
    ax.set_xlabel(str.capitalize(df_g.columns[0]))
    ax.set_ylabel(str.capitalize(df_g.columns[1]))
    ax.text(0.99, 0.01,"correlation:{0:.2}".format(cor),
                    horizontalalignment='right', verticalalignment='bottom',
                    fontsize=12,color="blue",transform=ax.transAxes)
    plt.show()

Figure setosa.png
Figure Versicolor.png
Figure Virginica.png

以上です。

おわりに

初めてQiitaに投稿してみます。
Qiitaには助けられることばかりでしたので、誰かの助けになればと思います。

参考文献

Pythonデータ分析/機械学習のための基本コーディング! pandasライブラリ活用入門 (impress top gear) (日本語) 単行本(ソフトカバー)
ISBN-10: 4295005657
ISBN-13: 978-4295005650

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2