前回は、PythonのMatplotlibライブラリがどのようにデータの可視化に使用できるかを見てきました。
今回は、Pythonのデータ可視化で非常に便利な別のライブラリであるSeabornについて見ていきます。
SeabornライブラリはMatplotlibの上に構築されており、多くの高度なデータ可視化機能を提供します。
Seabornライブラリは行列プロット、格子プロット、回帰プロットなど様々なグラフを描くことができますが、今回はSeabornライブラリを使って分布プロットやカテゴリプロットを描く方法を見ていきましょう。
第2回目では、回帰プロット、行列プロット、格子プロットの描き方を紹介します。
シーボーンライブラリーのダウンロード
seaborn` ライブラリはいくつかの方法でダウンロードすることができます。
Pythonライブラリのpip installerを使用している場合、以下のコマンドを実行してライブラリをダウンロードすることができます。
pip install seaborn
また、AnacondaディストリビューションのPythonを使用している場合は、以下のコマンドを実行して seaborn
ライブラリをダウンロードすることができます。
conda install seaborn
データセット
プロットを作成するために使用するデータセットは、Seabornライブラリと一緒にデフォルトでダウンロードされるTitanicデータセットである。
load_dataset` 関数を使って、データセット名を渡せばいいだけだ。
Titanicデータセットがどのようなものか見てみよう。
次のスクリプトを実行する。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
dataset = sns.load_dataset('titanic')
dataset.head()
上のスクリプトはTitanicデータセットをロードし、head関数を使ってデータセットの最初の5行を表示する。
出力はこのようになる。
このデータセットには891行と15列があり、不幸な船タイタニック号に乗り込んだ乗客に関する情報が含まれている。
本来の課題は、年齢、切符、乗った船室、切符のクラスなどの様々な特徴によって、乗客が生存しているかどうかを予測することである。
我々は、Seabornライブラリを使って、データの中に何かパターンを見つけることができるかどうかを確認する。
分布プロット
分布図とは、その名の通り、データの統計的分布を示すプロットの一種です。
このセクションでは、Seabornで最も一般的に使用される分布プロットをいくつか見ていきます。
ディスト・プロット
distplot()は、1つのカラムのデータのヒストグラム分布を表示します。
列の名前はdistplot()` 関数のパラメータとして渡されます。
各乗客のチケットの価格がどのように分布しているかを見てみましょう。
次のスクリプトを実行してください。
sns.distplot(dataset['fare'])
出力してください。
ほとんどのチケットが0-50ドルの間で解決されていることがわかります。
表示されている線は、カーネル密度推定を表しています。
以下のように、kde
属性のパラメータにFalse
を渡すことで、この線を消すことができます。
sns.distplot(dataset['fare'], kde=False)
出力されます。
これで、プロット上にカーネル密度推定を表す線がないことがわかると思います。
また、グラフの詳細を見るために、bins
パラメータに値を渡すことができます。
次のスクリプトを見てください。
sns.distplot(dataset['fare'], kde=False, bins=10)
ここでは、ビンの数を10に設定しています。
出力では、以下のように10ビンに分散されたデータが表示されます。
出力。
700人以上の乗客について、チケットの値段が0から50の間であることがよくわかります。
ジョイント・プロット
各列の相互分布を表示するには、jointplot()
を使用します。
jointplot` には 3 つのパラメータを渡す必要があります。
最初のパラメータは、X軸にデータの分布を表示したい列の名前です。
2つ目のパラメータは、Y軸にデータの分布を表示する列の名前です。
最後に、3番目のパラメータは、データフレームの名前です。
それでは、age
と fare
の列のジョイントプロットを行い、この2つの間に何か関係があるかどうか見てみましょう。
sns.jointplot(x='age', y='fare', data=dataset)
出力します。
出力から、ジョイントプロットは3つの部分からなることがわかります。
x軸上の列の上部の分布プロット、y軸上の列の右側の分布プロット、そして、両方の列のデータの相互分布を示すその間の散布図です。
価格と運賃の間に相関が観察されないことがわかります。
kindパラメータに値を渡すことで、ジョイントプロットの種類を変更することができます。
例えば、散布図ではなく、六角形のプロットの形でデータの分布を表示したい場合、kindパラメータに
hex` という値を渡します。
次のスクリプトを見てください。
sns.jointplot(x='age', y='fare', data=dataset, kind='hex')
出力
六角形プロットでは、最も多くのポイントを持つ六角形が暗い色になります。
つまり、上のプロットを見ると、乗客の多くは20歳から30歳で、チケット代も10-50ドル程度であることがわかります。
ペア・プロット
paitplot()は分布図の一種であり、基本的にはデータセット中の数値列と論理列の可能なすべての組み合わせについて、ジョイントプロットを行います。
以下のように、pairplot()` 関数のパラメータとしてデータセット名を渡すだけでよいのです。
sns.pairplot(dataset)
出力された部分のスナップショットを以下に示します。
注意: 上記のスクリプトを実行する前に、以下のコマンドを使ってデータセットからすべてのNULL値を削除してください。
dataset = dataset.dropna()
ペアプロットの出力から、Titanicデータセットのすべての数値列とブール列のジョイントプロットを見ることができます。
カテゴリカラムの情報をペアプロットに追加するには、 hue
パラメータにカテゴリカラムの名前を渡します。
例えば、性別の情報をペアプロットにプロットしたい場合は、以下のスクリプトを実行すればよい。
sns.pairplot(dataset, hue='sex')
出力
出力では、男性の情報はオレンジ色で、女性の情報は青色で表示されます(凡例に示すように)。
左上のジョイントプロットから、生存している乗客のうち、大多数が女性であることがよくわかります。
ラグ・プロット
rugplot()` は、データセットの各点に対して x 軸に沿って小さな棒グラフを描くために使用される。
ラグプロットを行うには、列の名前を渡す必要があります。
運賃についてラグプロットしてみましょう。
sns.rugplot(dataset['fare'])
を出力せよ。
出力から、distplot()
の場合と同様に、運賃のインスタンスのほとんどは0から100の間の値を持っていることがわかります。
これらは、PythonのSeabornライブラリが提供する最も一般的に使用される分布図です。
それでは、Seabornライブラリのカテゴリプロットのいくつかを見てみましょう。
カテゴリープロット
カテゴリプロットは、その名前が示すように、通常、カテゴリデータをプロットするために使用されます。
カテゴリプロットは、カテゴリ列の値を別のカテゴリ列または数値列に対してプロットします。
最も一般的に使用されるカテゴリカルデータをいくつか見てみましょう。
バー・プロット
barplot()` は、数値列に対するカテゴリ列の各値の平均値を表示するために使用される。
最初のパラメータはカテゴリ列、2番目のパラメータは数値列、3番目のパラメータはデータセットである。
例えば、男性乗客と女性乗客の年齢の平均値を知りたい場合、以下のように棒グラフを使うことができる。
sns.barplot(x='sex', y='age', data=dataset)
出力
出力から、男性乗客の平均年齢は40歳弱、女性乗客の平均年齢は約33歳であることがよくわかります。
平均を求めることに加えて、棒グラフは、各カテゴリの他の集計値を計算するのにも使うことができます。
これを行うには、 estimator
に集約関数を渡す必要があります。
例えば、各性別の年齢に対する標準偏差を次のように計算することができます。
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.barplot(x='sex', y='age', data=dataset, estimator=np.std)
上記のスクリプトでは、numpy
ライブラリの std
集約関数を使用して、男性と女性の乗客の年齢の標準偏差を計算していることに注意してください。
出力は以下のようになります。
伯爵の陰謀
count plot は bar plot に似ていますが、これは特定の列のカテゴリのカウントを表示します。
たとえば、男性と女性の乗客の数をカウントしたい場合、次のようにカウントプロットを使って行うことができます。
sns.countplot(x='sex', data=dataset)
出力は次のようにカウントを表示します。
出力は次のようになります。
出力:
ボックスプロット
箱ひげ図は、カテゴリデータの分布を四分位値で表示するために使用される。
箱の中心は中央値を示す。
下ヒゲから箱の底までの値は、第1四分位を示す。
箱の底から箱の真ん中までが第二四分位値です。
箱の真ん中から箱の上までが第3四分位値、最後に箱の上から上ひげまでが最終四分位値です。
四分位と箱ひげ図について、このリンクでもっと学ぶことができます。
では、それぞれの性別に関する年齢の分布を表示する箱ひげ図をプロットしてみましょう。
最初のパラメータとしてカテゴリカルカラム(この例では性別)、2番目のパラメータとして数値カラム(この例では年齢)を渡す必要があります。
最後に、3番目のパラメータとしてデータセットを渡します。
以下のスクリプトを見てください。
sns.boxplot(x='sex', y='age', data=dataset)
出力
女性の箱ひげ図を見てみましょう。
第一四分位は5歳から22歳までで、乗客の25%が5歳から25歳であることを意味します。
第2四分位は23歳から32歳までで、これは乗客の25%が23歳から32歳であることを意味します。
同様に、第3四分位は34から42の間で始まり、この範囲で終わるので、25%の乗客はこの範囲内の年齢であり、最後に第4または最後の四分位は43で始まり、65で終わります。
もし、外れ値やどの四分位にも属さない乗客がいれば、それは外れ値と呼ばれ、箱ひげ図上に点で表示されます。
分布の別のレイヤーを追加することで、箱ひげ図をより派手にすることができます。
例えば、男女の乗客の餌の箱ひげ図を、生存しているかどうかの情報とともに見たい場合は、以下のように hue
パラメータに survived
を値として渡すことができます。
sns.boxplot(x='sex', y='age', data=dataset, hue="survived")
出力
さて、男女それぞれの年齢に関する情報に加えて、生存した乗客の分布も見ることができます。
例えば、男性の乗客では、平均して若い人が年配の人に比べてより多く生き残っていることがわかります。
同様に、生存しなかった女性乗客の年齢のばらつきは、生存した女性乗客の年齢よりはるかに大きいことがわかります。
ヴァイオリン・プロット
バイオリンプロットはボックスプロットに似ているが、バイオリンプロットは実際にデータ点に対応するすべての成分を表示することができる。
バイオリンプロットを描くには、 violinplot()
関数が使用される。
箱ひげ図と同様、最初のパラメータはカテゴリ列、2番目のパラメータは数値列、3番目のパラメータはデータセットです。
ここでは、性別ごとの年齢分布を表示するバイオリンプロットをプロットしてみましょう。
sns.violinplot(x='sex', y='age', data=dataset)
出力
上の図から、バイオリンプロットはボックスプロットと比較して、データについてより多くの情報を提供することがわかります。
四分位をプロットする代わりに、バイオリンプロットは、実際にデータに対応するすべての成分を見ることができます。
バイオリンプロットが厚い領域は、年齢に対するインスタンスの数が多い。
例えば、男性のバイオリンプロットから、20歳から40歳の乗客の数が、他のすべての年齢層よりも多いことがはっきりとわかります。
箱ひげ図と同様に、以下のように hue
パラメータを使用して、別のカテゴリ変数をバイオリンプロットに追加することも可能です。
sns.violinplot(x='sex', y='age', data=dataset, hue='survived')
これでバイオリンプロット上に多くの情報を見ることができるようになりました。
たとえば、生存した雄のバイオリンプロットの底(左オレンジ)を見ると、生存しなかった雄のバイオリンプロットの底(左青)よりも厚くなっていることがわかります。
これは、生き残った若い男性の乗客の数が、生き残らなかった若い男性の乗客の数より多いことを意味します。
バイオリンプロットは多くの情報を伝えてくれますが、欠点としては、バイオリンプロットを理解するのに少し時間と労力がかかるということです。
生き残った乗客とそうでない乗客の2種類のグラフを描く代わりに、1つのバイオリンプロットを2つに分けて、半分は生き残った乗客、もう半分はそうでない乗客を表すようにすることができます。
これを行うには、 violinplot()
関数の split
パラメータに True
を渡す必要があります。
それでは、どのようにすればよいかを見てみましょう。
sns.violinplot(x='sex', y='age', data=dataset, hue='survived', split=True)
出力はこのようになります。
これで、生き残った乗客とそうでない乗客の年齢を、男性と女性の両方で比較することがはっきりとわかります。
バイオリン図と箱ひげ図は、両方とも非常に便利です。
しかし、専門家でない聴衆にデータを見せる場合は、理解しやすい箱ひげ図が好まれます。
一方、研究者に発表する場合は、バイオリンプロットを使用した方が、スペースを節約でき、短時間でより多くの情報を伝えることができます。
ストリップ・プロット
ストリッププロットは、変数の1つがカテゴリである場合の散布図を描きます。
我々は、2つの数値変数があるジョイントプロットやペアプロットのセクションで散布図を見てきました。
ストリッププロットは、この場合、変数の1つがカテゴリであるという点で異なっており、カテゴリ変数の各カテゴリについて、数値列に対する散布図を見ることができます。
stripplot()` 関数は、バイオリンプロットを作成するために使用されます。
箱ひげ図と同様、最初のパラメータはカテゴリー列、2番目のパラメータは数値列、3番目のパラメータはデータセットです。
次のスクリプトを見てください。
sns.stripplot(x='sex', y='age', data=dataset)
出力。
男性と女性の年齢の散布図が見えます。
データ点は短冊のように見える。
このような形のデータでは、データの分布を理解することは困難です。
データをよりよく理解するために、jitter
パラメータにTrue
を渡すと、データにランダムなノイズが加わります。
次のスクリプトを見てください。
sns.stripplot(x='sex', y='age', data=dataset, jitter=True)
出力
これで性別ごとの年齢分布がよくわかるようになりました。
バイオリンプロットや箱ひげ図と同様に、以下のように hue
パラメータを使ってストリッププロットにカテゴリカラムを追加することができます。
sns.stripplot(x='sex', y='age', data=dataset, jitter=True, hue='survived')
ここでも、プロットの底部付近で生存した男性について、生存しなかった男性と比較してより多くのポイントがあることがわかります。
バイオリンプロットと同様に、ストリッププロットも分割することができます。
次のスクリプトを実行します。
sns.stripplot(x='sex', y='age', data=dataset, jitter=True, hue='survived', split=True)
出力
これで、生き残った乗客とそうでない乗客の年齢分布の違いがはっきりわかる。
スウォームプロット
群プロットは、ストリッププロットとバイオリンプロットの組み合わせである。
群プロットでは、ポイントが重ならないように調整される。
性別に対する年齢の分布について、群プロットをプロットしてみましょう。
swarmplot()`関数は、バイオリンプロットをプロットするために使用されます。
箱ひげ図と同じように、最初のパラメータはカテゴリ列、2番目のパラメータは数値列、3番目のパラメータはデータセットです。
次のスクリプトを見てください。
sns.swarmplot(x='sex', y='age', data=dataset)
上のプロットは、ストリッププロットのようにデータ点が散らばっていて、データ点が重なっていないことがよくわかります。
むしろ、それらはバイオリンプロットに似た表示をするように配置されています。
hue` パラメータを使って、swarm プロットにもう1つのカテゴリ列を追加してみましょう。
sns.swarmplot(x='sex', y='age', data=dataset, hue='survived')
出力します。
出力から、生存する雄の比率は生存する雌の比率より小さいことがわかります。
男性のプロットでは、青い点が多く、オレンジの点が少ないからです。
一方、女性では、オレンジ色の点(生存)が青色の点(生存していない)より多くなっています。
また、年齢が10歳未満の男性では、生き残った乗客の方が、そうでない乗客よりも多いという観察結果もあります。
帯グラフや箱グラフの場合と同じように、群グラフを分割することもできます。
次のスクリプトを実行してください。
sns.swarmplot(x='sex', y='age', data=dataset, hue='survived', split=True)
出力
これで、男性に比べて女性の方がより多く生存していることがはっきりとわかります。
スウォームプロットとバイオリンプロットの組み合わせ
群プロットは、各データポイントをプロットしなければならないので、うまくスケールしないので、巨大なデータセットを持っている場合は推奨されません。
もし、あなたが群管理図を本当に好きなら、よりよい方法は、2つの管理図を組み合わせることです。
例えば、バイオリンプロットと群プロットを組み合わせるには、次のスクリプトを実行する必要があります。
sns.violinplot(x='sex', y='age', data=dataset)
sns.swarmplot(x='sex', y='age', data=dataset, color='black')
出力
この連載はSeabornの使い方を詳しく紹介することを目的としていますが、数回のブログ投稿ではカバーしきれない詳細がたくさんあります。
また、Python用の可視化ライブラリは他にもたくさんあり、Seabornでできること以上の機能を備えているものもあります。
Seaborや他の8つのライブラリを使ってPythonでデータを可視化するための、より詳細なガイドについては、Data Visualization in Pythonをご覧ください。
結論
Seaborn は Matplotlib ライブラリ上に構築された高度なデータ可視化ライブラリです。
今回は、Seabornライブラリを使って、分布図やカテゴリ図を描く方法について見ていきました。
この記事はSeabornに関する連載の第1回目です。
第2回目では、Seabornのグリッド機能を使った遊び方や、Seabornで行列プロットや回帰プロットを描く方法について見ていきたいと思います。