You are currently viewing plotnine:ggplot2を使ってテータの分布を可視化する〜Python

plotnine:ggplot2を使ってテータの分布を可視化する〜Python

Pythonの可視化ツールとして、MatplotlibとSeabornが有名です。MatplotlibとSeabornは非常に複雑なグラフを作ることができますが、グラフを完成するまで時間がかかりますし、グラフを構成する要素をコントロールすることは簡単ではありません。それに対してR言語のggplot2は簡単にデータ分析に必要なグラフを作れるので、MatplotlibとSeabornよりデータ分析に向いているでしょう。実はplotnineというライブラリが出てきて、Pythonでもggplot2を使えるようになっています。この記事ではPython版のggplot2を使って、データの分布の可視化について話をします。

  • ヒストグラム
  • 密度プロット
  • 箱ひげ図
  • バイオリンプロット
  • 各プロットを重ね合わせて最強のグラフを作ろう

plotninenのインストール等は公式サイトをご参照ください。現在ベータ版しかありませんので、バグにはまらないように最新バージョンをインストールしましょう。

データ分析にせよ、機械学習にせよ、先にデータの分布を確認することは重要なタスクです。データ分析する際に、平均値、標準偏差等の統計指標のみを確認すると、データの重要な性質を見落とす可能性があります。また、機械学習において、ほとんどのアルゴリズムはデータの分布に対して仮説を持っているので、データの分布を確認せずにモデリングすると良い結果を得られません。

データセット

irisデータセットを使って説明しますので、まずはデータを読み込みます。

from sklearn.datasets import load_iris
import pandas as pd

iris = load_iris()
X = iris.data

iris_df = pd.DataFrame(pd.DataFrame(iris.data, columns=iris.feature_names))
iris_df['irises'] = [list(iris.target_names)[e] for e in iris.target]
display(iris_df.head()) 

データの意味は以下のとおりです:

カラム名意味
sepal length (cm)がく片の長さ
sepal width (cm)がく片の幅
petal length (cm)花弁の長さ
petal width (cm)花弁の幅
iris花の種類
setosa、versicolor、virginicaの3種類がある

この記事ではsepal width (cm)(がく片の幅)の分布のみを確認しますが、他のカラムの分布に興味があればぜひ同じ方法でやって見てください。

ヒストグラム

度数分布表を棒グラフにしたものはヒストグラムと呼びます。度数分布表はデータを階級で区切り、各階級のデータをカウントした表になります。

以下の処理で度数分布表を作ります。データを均等に13個の階級に分割し、各階級のデータをカウントします:

cut = pd.cut(iris_df['sepal width (cm)'], 13).value_counts()
cut.sort_index() 
(1.998, 2.185]     1
(2.185, 2.369]     7
(2.369, 2.554]    11
(2.554, 2.738]    14
(2.738, 2.923]    24
(2.923, 3.108]    37
(3.108, 3.292]    13
(3.292, 3.477]    18
(3.477, 3.662]    10
(3.662, 3.846]     9
(3.846, 4.031]     3
(4.031, 4.215]     2
(4.215, 4.4]       1
Name: sepal width (cm), dtype: int64

ヒストグラムは棒グラフなので、階級が一つ一つの棒で表現されるのですが、習慣的にヒストグラムの棒をビンと呼びます。

以下の処理で、ビンの数を指定することで、ヒストグラムを作ります:

from plotnine import *

(
    ggplot(iris_df, aes('sepal width (cm)'))
    + geom_histogram(bins = 13)
) 

ヒストグラムをみると、sepal width (cm)(がく片の幅)の中央値は3前後であることが分かります。

ビンの数を調整することで、全然形の違うビストグラムが出来上がりますので、無意味なヒストグラムを作らないように調整しましょう。

(
    ggplot(iris_df, aes('sepal width (cm)'))
    + geom_histogram(bins = 3)
) 

ビンの数を3に指定するとヒストグラムの意味がなくなりますね。

次に、irisの花は3種類があるということなので、それぞれの種類に対してヒストグラムを作りたいと思います。fillパラメータにDataFrameのirisesカラムを指定すると、irisesカラムにある3種類の花に対してそれぞれのヒストグラムを作ります。

(
    ggplot(iris_df, aes('sepal width (cm)', fill = 'irises'))
    + geom_histogram(bins = 13, position = "identity", alpha = 0.7)
) 

確率密度プロット

ヒストグラムと似ていて、データの数を極限まで増やし、階級の幅を極限まで縮めると、ヒストグラムは平滑な曲線で表現できます。これはカーネル密度推定(kernel-density estimation)という手法で推定できます。さらに曲線と横軸の間の面積が1になるようにカーネル密度推定されるのは確率密度関数になります。詳しく展開しませんが、面積が1(100%)は確率の名前の由来です。

以下の処理で確率密度プロットを作りますが、adjustパラメータを大きくすると、確率密度関数が平滑になります:

(
    ggplot(iris_df, aes('sepal width (cm)', fill = 'irises'))
    + geom_density(alpha = 0.7, adjust = 0.85)
) 

縦軸の数字はヒストグラムと違ってカウントではありません。カーネル密度推定により産出された数値なので、特に気にする必要はありません。

箱ひげ図

箱ひげ図は四分位を利用してデータの分布示すグラフです。

箱ひげ図は特にデータの外れ値を特定するのに役に立ちます。

以下の処理で箱ひげ図を作ります:

(
    ggplot(iris_df, aes('irises', 'sepal width (cm)', fill = 'irises'))
    + geom_boxplot()
) 

irisの3種類の花の箱ひげ図をそれぞれプロットしました。

  • 四角:四角の部分はデータの四分位範囲(interquartile range, IQR)を示しています。つまり、データの25パーセンタイルから75パーセンタイルがこの箱に入っています。
  • 箱にある横線:データの中央値を示しています。
  • 縦線:四角の上端/下端からIQR × 1.5の範囲
  • :外れ値(IQR × 1.5より外側の値)

バイオリンプロット

バイオリンプロットは確率密度プロットを縦にプロットするようなグラフです。但し、バイオリンプロット単品だと確率密度プロットの方が分かりやすいので、この後色んなグラフと重ね合わせることで、有意義に使います。

(
    ggplot(iris_df, aes('irises', 'sepal width (cm)', fill = 'irises'))
    + geom_violin()
) 

各プロットを重ね合わせて最強のグラフを作ろう

(
    ggplot(iris_df, aes('irises', 'sepal width (cm)', fill = 'irises'))
    + geom_violin()
    + geom_boxplot()
    + geom_point(position = position_jitter(width = 0.1, height = 0))
) 

上記のグラフは箱ひげ図、バイオリンプロット、ストリッププロットの3種類で構成されます。データの分布、外れ値、中央値等の情報を一つのグラフにまとめましたので特にこだわりがなければ普段このグラフを使うのが良いでしょう。

順に

  1. geom_violinでバイオリンプロットを描く
  2. geom_boxplotで箱ひげ図を描く
  3. geom_pointでストリッププロットを描く ※図中の黒いドットたちがストリッププロットになります。

まとめ

データの分布を確認することの重要性はいうまでもないが、今回の記事ではデータの分布の可視化についてご紹介しました。

  • ヒストグラム
  • 密度プロット
  • 箱ひげ図
  • バイオリンプロット
  • 各プロットを重ね合わせて最強のグラフを作ろう