CozyRats Notebook

Pythonや機械学習、データの可視化について書きます。

Plotlyでインタラクティブな散布図を作成する

はじめに

Pythonでデータの可視化をする際に、 matplotlibseaborn を使う機会が多いのですが、インタラクティブに見せたい場合に Plotly を時々利用してきました。

ただ、あまり深く理解しきれていなかったのでいろいろと触ってみましたので使い方などを記載します。

データ作成

最初に、必要なモジュールとデータセットをインポートします。

import numpy as np
import pandas as pd
import plotly.express as px
from sklearn.datasets import load_wine

データを読み込み、構造を見てみます。

data = load_wine()
print(data['data'])
print(data['feature_names'])
print(data['target'])
print(data['target_names'])
[[1.423e+01 1.710e+00 2.430e+00 ... 1.040e+00 3.920e+00 1.065e+03]
 [1.320e+01 1.780e+00 2.140e+00 ... 1.050e+00 3.400e+00 1.050e+03]
 [1.316e+01 2.360e+00 2.670e+00 ... 1.030e+00 3.170e+00 1.185e+03]
 ...
 [1.327e+01 4.280e+00 2.260e+00 ... 5.900e-01 1.560e+00 8.350e+02]
 [1.317e+01 2.590e+00 2.370e+00 ... 6.000e-01 1.620e+00 8.400e+02]
 [1.413e+01 4.100e+00 2.740e+00 ... 6.100e-01 1.600e+00 5.600e+02]]
['alcohol', 'malic_acid', 'ash', 'alcalinity_of_ash', 'magnesium', 'total_phenols', 'flavanoids', 'nonflavanoid_phenols', 'proanthocyanins', 'color_intensity', 'hue', 'od280/od315_of_diluted_wines', 'proline', array(['class_0', 'class_1', 'class_2'], dtype='<U7')]
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
['class_0' 'class_1' 'class_2']

今回データの可視化がメインのため、dataとtargetを結合して、targetをTargetというカラムに変更します。

data['feature_names'][-1] = 'Target'
df = pd.DataFrame(data=np.hstack((data['data'], data['target'].reshape(178,1))), columns=data['feature_names'])
df

散布図 Scatter Plots

基本のグラフ

散布図はこちら、seabornとほとんど書き方は同じようです。

fig = px.scatter(df, x='alcohol', y='malic_acid', color='Target')
fig.size()

サイズが見づらいので調整します。

fig = px.scatter(df, x='alcohol', y='malic_acid', color='Target', width=600, height=600)
fig.show()

HTML出力&埋め込み

Htmlに出力して、このブログにも貼り付けてみます。 コードは短縮用のHTMLを生成し、クリップボードにHTMLをコピーする挙動です。

import pyperclip
pyperclip.copy(fig.to_html(include_plotlyjs='cdn',full_html=False))

生成したHTMLが以下になります、マウスオーバーをさせることでデータが表示されます。ぜひいろいろと触ってみてください。

プロットがグラデーションになっていますが、Targetは0、1、2の3つしかないため、本来であればカテゴリカルに扱いたいです。

そうしたい場合はどうやらTargetをstring型に変更してから表示させることになりそうです。

df['Target'] = df['Target'].astype(str)
fig = px.scatter(df, x='alcohol', y='malic_acid', color='Target', width=600, height=600)
fig.show()

散布図とヒストグラムを同時に表示させる

縦軸、横軸にデータの分布を合わせて表示させることができます。これはデータの外観を掴むのに非常に便利そうです。 ヒストグラム以外にも箱ひげや、バイオリンプロットも表示できます。

fig = px.scatter(df, x='alcohol', y='malic_acid', color='Target', marginal_x='histogram', marginal_y='violin', width=800, height=800)
fig.show()

縦横分割して表示させる

facet_row 、facet_col を指定することで、グラフ自体を分割して表示することができます。

fig = px.scatter(df, x='alcohol', y='malic_acid', facet_col='Target', marginal_x='histogram', width=800, height=800, color='ash')
fig.show()

回帰直線を入れる

trendlineを入れることで、回帰直線を入れたりすることができるようです。マウスホバーをすることで決定係数も表示されます。

fig = px.scatter(df, x='total_phenols', y='flavanoids', color='Target', trendline="ols", width=800, height=800)
fig.show()

色の変更

上記グラフを見る限り、グラフの色が少し見づらいところがあるので、変更します。 色だけでなく、グラフ全体のレイアウトなどを変更する際には、 import plotly.graph_objects as go モジュールをつかうようですが、こちらはまた別で試してみようと思います。

おわりに

折線グラフや棒グラフ、円グラフ、バブルチャートなど他にもいろいろとありそうですが、また別の機会に紹介したいと思います。