Pandas.DataFrameの要素をグルーピングするGroupByを丁寧に解説!

こんにちは!インストラクターのフクロウです!この記事では、pandas.DataFrameの要素をグルーピングする事ができるGroupByを解説します。

あるDataFrameを、任意の条件でいくつかの小さなDataFrameに分割してそれぞれに対して演算したい、ということがあります。こんな時、GroupByを使うと簡単にそれが実現できますよ!

目次

開発環境

この記事を書くために使った開発環境は以下のとおりです。

ライブラリのバージョンなど

  • OS=”Ubuntu 18.04.1 LTS”
  • Python 3.7.0
  • Pandas 0.23.4

OSが異なっても基本的には同じ操作で記事中のプログラムは再現できるので、試してみてください!

groupbyの使い方

[前準備]DataFrameの作成

まずライブラリをimportしておきましょう。そして機械学習ライブラリsklearnからiris datasetsを読み込んで、DataFrameを作ります。

In [1]:
import pandas as pd
import numpy as np
from sklearn import datasets

# sklearnからデータセットを読み込みます
iris = datasets.load_iris()

# データセットからDataFrameを作成します。ここでは列が特徴になっていて、クラスをlabel列として追加しておきます。
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df["label"] = [iris.target_names[i] for i in iris.target]
df.head()
Out[1]:
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) label
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa

groupbyメソッドの使い方

groupbyは特定の列の値ごとにグループを作成することができます。グループごとに統計量を計算するなどの使い方ができます。

例えば、label列の要素は全部で3つ、[setosa,versicolor,virginica]です。この3つのグループを一つのDataFrameから作成して、それぞれに対してmaxやstd、sumなどの関数を適用できます。

In [2]:
df.groupby("label")
Out[2]:
<pandas.core.groupby.groupby.DataFrameGroupBy object at 0x7f2b142f00f0>

groupbyで作ったグループは、pandasの特殊なオブジェクトになっているのでprintして中身を確認することができません。ですがちゃんとそれぞれをDataFrameとして扱い、計算ができるので確かめてみましょう。

groupbyを使ったグループごとの計算

In [3]:
# グループごとに合計値を出す 
df.groupby("label").sum()
Out[3]:
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
label
setosa 250.3 171.4 73.1 12.3
versicolor 296.8 138.5 213.0 66.3
virginica 329.4 148.7 277.6 101.3
In [4]:
# グループごとに分散を出す 
df.groupby("label").var()
Out[4]:
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
label
setosa 0.124249 0.143690 0.030159 0.011106
versicolor 0.266433 0.098469 0.220816 0.039106
virginica 0.404343 0.104004 0.304588 0.075433

出力される結果はグループの分だけ行があり、それぞれのグループで計算ができていることがわかります。さらに、統計量の計算はdescribeメソッドを使えば一発で一覧が出せます。これもgroupbyで使えるので試してみましょう。

In [5]:
# グループごとに統計量一覧を出す 
df.groupby("label").describe().T
Out[5]:
label setosa versicolor virginica
petal length (cm) count 50.000000 50.000000 50.000000
mean 1.462000 4.260000 5.552000
std 0.173664 0.469911 0.551895
min 1.000000 3.000000 4.500000
25% 1.400000 4.000000 5.100000
50% 1.500000 4.350000 5.550000
75% 1.575000 4.600000 5.875000
max 1.900000 5.100000 6.900000
petal width (cm) count 50.000000 50.000000 50.000000
mean 0.246000 1.326000 2.026000
std 0.105386 0.197753 0.274650
min 0.100000 1.000000 1.400000
25% 0.200000 1.200000 1.800000
50% 0.200000 1.300000 2.000000
75% 0.300000 1.500000 2.300000
max 0.600000 1.800000 2.500000
sepal length (cm) count 50.000000 50.000000 50.000000
mean 5.006000 5.936000 6.588000
std 0.352490 0.516171 0.635880
min 4.300000 4.900000 4.900000
25% 4.800000 5.600000 6.225000
50% 5.000000 5.900000 6.500000
75% 5.200000 6.300000 6.900000
max 5.800000 7.000000 7.900000
sepal width (cm) count 50.000000 50.000000 50.000000
mean 3.428000 2.770000 2.974000
std 0.379064 0.313798 0.322497
min 2.300000 2.000000 2.200000
25% 3.200000 2.525000 2.800000
50% 3.400000 2.800000 3.000000
75% 3.675000 3.000000 3.175000
max 4.400000 3.400000 3.800000

groupbyを使ったグループごとの可視化

可視化もいけます!plotメソッドで個別にプロットしてみましょう。

In [7]:
df.groupby("label").plot(kind="scatter", # 散布図を作成 
           x=0, y=1) # x軸とy軸を指定
Out[7]:
label
setosa        AxesSubplot(0.125,0.125;0.775x0.755)
versicolor    AxesSubplot(0.125,0.125;0.775x0.755)
virginica     AxesSubplot(0.125,0.125;0.775x0.755)
dtype: object
このようにDataFrameのメソッドでできることは大体できるので、応用がいくらでも効きそうな機能ですね。

まとめ

この記事では、DataFrameの要素を内部でグルーピングするメソッド、groupbyを紹介しました。

groupbyの要点

  • groupbyはDataFrameのメソッド
  • groupbyでDataFrameの要素を列の値を使ってグルーピングできる
  • 統計量やプロットをグループごとに出力できる


groupbyを使えばloc/ilocなどを使ってスライスしなくても、手軽にDataFrameを分割できます。データの全体像を見るのに非常に便利な機能です。ぜひ使ってみてください。

この記事を書いた人

第一言語はPythonです。
皆さんRustやりましょう。

目次