Python には多くのデータ可視化ライブラリがありますが、Matplotlib はその中でも最も人気のあるライブラリです。
Matplotlib の人気の理由はその信頼性と実用性にあり、少ないコードでシンプルなプロットから複雑なプロットまで作成することができます。
また、プロットは様々な方法でカスタマイズすることができます。
このチュートリアルでは、Matplotlib で、散布図と複数の分布図からなるジョイントプロットを、同じ Figure
上に作成する方法を説明します。
ジョイントプロットは、二変量データ間の関係や、その分布を同時に調べるために使用します。
注:この種のタスクは、ビルトインの jointplot()
関数を持つ Seaborn のようなライブラリにずっと適しています。
Matplotlib では、Seaborn の代わりに GridSpec
と複数の Axes
オブジェクトを使用して、手動でジョイントプロットを作成します。
データのインポート
ここでは、有名なアイリスのデータセットを使用します。
散布図で SepalWidthCm
や SepalLengthCm
などの特徴量の関係を調べると同時に、分布図で萼片の長さや幅を考慮した Species
特徴量間の分布も調べることができるからです。
それでは、データセットをインポートして、見てみましょう。
import pandas as pd
df = pd.read_csv('iris.csv')
print(df.head())
この結果
Id SepalLengthCm SepalWidthCm PetalLengthCm PetalWidthCm Species
0 1 5.1 3.5 1.4 0.2 Iris-setosa
1 2 4.9 3.0 1.4 0.2 Iris-setosa
2 3 4.7 3.2 1.3 0.2 Iris-setosa
3 4 4.6 3.1 1.5 0.2 Iris-setosa
4 5 5.0 3.6 1.4 0.2 Iris-setosa
ここでは、SepalLengthCm
と SepalWidthCm
の特徴量の二変量関係を調べると同時に、それらの分布も調べます。
これには2つの方法があります – 「種」を考慮するかしないかです。
種(Species)」を全く無視し、各花の分布のヒストグラムを単純にプロットすることができます。
一方、各花の分布図を色分けしてプロットし、「種」の違いも強調することができます。
ここでは、より単純な方、つまり Species
を完全に無視することから始めて、両方の選択肢を探ってみることにします。
Matplotlib で単一クラスヒストグラムでジョイントプロットを作成する
最初のアプローチでは、花のインスタンスをロードして、そのままプロットします。
ここでは、図のレイアウトをカスタマイズするために GridSpec
を使用して、3つの異なるプロットと Axes
インスタンスに対応するスペースを確保します。
GridSpec` のコンストラクタを呼び出すには、PyPlot のインスタンスと一緒にインポートする必要があります。
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
それでは、 Figure
を作成して Axes
オブジェクトを作成しましょう。
df = pd.read_csv('iris.csv')
fig = plt.figure()
gs = GridSpec(4, 4)
ax_scatter = fig.add_subplot(gs[1:4, 0:3])
ax_hist_y = fig.add_subplot(gs[0,0:3])
ax_hist_x = fig.add_subplot(gs[1:4, 3])
plt.show()
図にサブプロットを追加し、それらを配置するために GridSpec
インスタンスを使用して、3つの Axes
インスタンスを作成しました。
この結果、3つの空の Axes
インスタンスを持つ Figure
ができあがります。
これでレイアウトと位置決めができたので、あとはデータを Axes
にプロットするだけです。
ここでは、SepalLengthCm
と SepalWidthCm
の特徴を散布図として ax_scatter
軸に、それぞれの特徴を ax_hist_y
と ax_hist_x
軸にプロットするようにスクリプトを更新してみましょう。
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
df = pd.read_csv('iris.csv')
fig = plt.figure()
gs = GridSpec(4, 4)
ax_scatter = fig.add_subplot(gs[1:4, 0:3])
ax_hist_x = fig.add_subplot(gs[0,0:3])
ax_hist_y = fig.add_subplot(gs[1:4, 3])
ax_scatter.scatter(df['SepalLengthCm'], df['SepalWidthCm'])
ax_hist_x.hist(df['SepalLengthCm'])
ax_hist_y.hist(df['SepalWidthCm'], orientation = 'horizontal')
plt.show()
ax_hist_yの
orientationを
horizontal` に設定し、散布図の右側に水平にプロットされるようにしました。
この結果、SepalLengthCm
と SepalWidthCm
の特徴の関係、およびそれぞれの特徴の分布がジョイントプロットされます。
Matplotlib で複数クラスヒストグラムのジョイントプロットを行う
さて、もう1つのケースとして、花の「種」に対するこれらの特徴の分布を調べたいと思います。
このために、各軸に1つのヒストグラムを使用し、それぞれにすべての花のインスタンスを含めるのではなく、両方の軸にそれぞれの「種」のヒストグラムを重ねます。
そのためには、まず今まで使っていた DataFrame
を、花の Species
ごとに分解する必要があります。
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
df = pd.read_csv('iris.csv')
setosa = df[df['Species']=='Iris-setosa']
virginica = df[df['Species']=='Iris-virginica']
versicolor = df[df['Species']=='Iris-versicolor']
species = df['Species']
colors = {
'Iris-setosa' : 'tab:blue',
'Iris-versicolor' : 'tab:red',
'Iris-virginica' : 'tab:green'
}
ここでは、DataFrame
を Species
機能でフィルタリングして、3つのデータセットに分離しています。
setosa、
virginica、
versicolor` の各データセットには、それぞれのインスタンスのみが含まれるようになります。
また、散布図とヒストグラムの両方で、それぞれのインスタンスを「種」に基づいて異なる色で表示したいと思います。
そのために、Species
機能の Series
を切り出して、colors
辞書を作成します。
この辞書を使って、後でそれぞれの花の Species
を色に map()
することになります。
それでは、Figure
, GridSpec
, Axes
のインスタンスを作成してみましょう。
fig = plt.figure()
gs = GridSpec(4, 4)
ax_scatter = fig.add_subplot(gs[1:4, 0:3])
ax_hist_y = fig.add_subplot(gs[0,0:3])
ax_hist_x = fig.add_subplot(gs[1:4, 3])
最後に、散布図とヒストグラムをプロットして、色と向きを設定します。
ax_scatter.scatter(df['SepalLengthCm'], df['SepalWidthCm'], c=species.map(colors))
ax_hist_y.hist(versicolor['SepalLengthCm'], color='tab:red', alpha=0.4)
ax_hist_y.hist(virginica['SepalLengthCm'], color='tab:green', alpha=0.4)
ax_hist_y.hist(setosa['SepalLengthCm'], color='tab:blue', alpha=0.4)
ax_hist_x.hist(versicolor['SepalWidthCm'], orientation = 'horizontal', color='tab:red', alpha=0.4)
ax_hist_x.hist(virginica['SepalWidthCm'], orientation = 'horizontal', color='tab:green', alpha=0.4)
ax_hist_x.hist(setosa['SepalWidthCm'], orientation = 'horizontal', color='tab:blue', alpha=0.4)
plt.show()
map()の呼び出しは、色の
Series` を生成します。
0 tab:blue
1 tab:blue
2 tab:blue
3 tab:blue
4 tab:blue
...
145 tab:green
146 tab:green
147 tab:green
148 tab:green
149 tab:green
scatter()関数の
c` 引数に指定すると、この順序でインスタンスに色を適用し、各インスタンスにその種に対応する色を効果的に付けます。
ヒストグラムの場合は、単純に3つのプロットを作成し、それぞれの Species
に対応する色をつけています。
ここでは、step
ヒストグラムを選択し、alpha
値を微調整して、異なる外観の分布を作成することができます。
このコードを実行すると、次のような結果が得られます。
これで、それぞれの「種」は独自の色と分布を持ち、他の花とは別にプロットされるようになりました。
さらに、散布図と一緒に色分けされているので、本当に直感的なプロットで、簡単に読み解くことができます。
注意:赤と青のヒストグラムを構成するオレンジのような、重なり合った色が邪魔に感じる場合は、histtype
をstep
に設定すると、塗りつぶした色を取り除くことができます。
結論
このガイドでは、Matplotlib でジョイントプロット (Scatter Plot) を描く方法を紹介しました。
この作業は、Seabornのようなジョイントプロットを内蔵したライブラリに適していますが、Matplotlibは、Seabornが簡単にこれらのプロットを作成できるようにするための基礎となるエンジンです。
もしあなたがデータ可視化に興味があり、何から始めたらよいかわからない場合は、Pythonによるデータ可視化に関する書籍の束をチェックしてみてください。
Pythonによるデータ可視化
データビジュアライゼーションで危険な存在になる
30日間無条件返金保証
初級から上級まで
定期的に無料で更新(最新更新は2021年4月)
ボーナスリソースやガイドを更新
Pythonでデータ可視化 MatplotlibとPandasは、Pythonの基礎知識を持つ全くの初心者が、PandasとMatplotlibを使って、単純なプロットからインタラクティブなボタンを持つアニメーションの3Dプロットまで、これらのライブラリで高度な作業をするための強力な基盤を構築できるように設計された書籍です。
本書は、Pythonの基本的な知識を持つ方を対象としています。
PandasとMatplotlibについて知っておく必要があることすべてを教えてくれる詳細なガイドです。
Pythonでデータ可視化」は、Pythonの初級~中級開発者向けの本で、Pandasを使った簡単なデータ操作から、MatplotlibやSeabornといったコアなプロットライブラリを取り上げ、Altairのような宣言的・実験的なライブラリの活用方法まで、幅広くガイドしています。
具体的には、11章にわたって、9つのPythonライブラリを取り上げています。
Pandas、Matplotlib、Seaborn、Bokeh、Altair、Plotly、GGPlot、GeoPandas、そしてVisPyです。
データビジュアライゼーションのユニークで実用的なガイドとして、あなたがキャリアで使うかもしれない多くのツールを紹介しています。