Plotlyでインタラクティブなグラフを描き、iframeで埋め込む

Plotly
PlotlyPython
0

せっかくブログに載せるなら、拡大・縮小、移動、値の表示などができる、インタラクティブなグラフを載せたい。

Plotlyというライブラリを使えば簡単にhtmlファイルとしてインタラクティブなデータの可視化をすることができ、ウェブサイトに埋め込むことができる。
本記事ではplotlyを用いてインタラクティブなグラフの作成方法を紹介する。

スポンサーリンク

Plotlyとは

Plotlyはオープンなライブラリであり、会社でもある。
無料でほとんどの機能が使えるが、オンラインで非公開なグラフを作るときや、さらに高度なことをしたい場合は有料になる。

僕は論文用のグラフはmatplotlibやseabornを使っている。
しかし、これらは静的な画像(PNGやPDFなど)を作るのに限定されている。
Plotlyはこだわった図を作りたいときにはやや使いづらい印象があるのだが、インタラクティブな図を簡単に作ることができる。

Pythonだけではなく、R、Javascript、Reactに向けてライブラリが用意されている。
本記事ではPythonの紹介をする。

ブログに貼り付けたいときはPlotly Chart Studioのアカウント登録し、APIキーを取得する必要がある。
そして、Chart Studio上に保存することでiframeを使って「リンクを貼り付ける」感覚でとても簡単にブログにグラフを埋め込むことができる。

それ意外の用途で使う場合はオフラインで通常のライブラリとして使えるので、インストールして使ってみてほしい。
(オンラインでは日本語に対応していないのだが、オフラインでは日本語も使うことができる。)

スポンサーリンク

インタラクティブなグラフの例

2次元グラフ

たとえば、指数分布の記事に載せた次のグラフ。

カーソルを合わせると数値が表示されたり、範囲を選択すると拡大ができたりする。
右上の「pan」を選択すると移動もできる。
グラフの右上の操作パネルからしたい操作を選択し、自由に動かすことができる。
(ダブルクリックで元に戻る。)
スマホは少し操作しづらいかも。

上のグラフのコードはこちら。

import numpy as np
import matplotlib.pyplot as plt
import chart_studio
import chart_studio.plotly as py
from plotly.subplots import make_subplots
import plotly.graph_objects as go

# usernameとAPI keyを指定
chart_studio.tools.set_credentials_file(username='YOUR_NAME', api_key='YOUR_API_KEY')

# xとλを設定
x = np.linspace(0, 5, 101)
l = np.linspace(0.5, 2, 4)

# 確率密度分布と累積分布関数を求める
f = l[:, None] * np.exp(- l[:, None] * x)
F = 1 - np.exp(- theta[:, None] * x)

# 色はmatplotlibのデフォルト(Plotlyのデフォルト色は嫌い)
color = plt.rcParams['axes.prop_cycle'].by_key()['color']

# 2つのグラフを表示
fig = make_subplots(rows=2, cols=1, subplot_titles=('$f(x)$','$F(x)$'))

# ラインを1つずつプロット
for i in range(len(l)):
    trace0 = go.Scatter(x=x, y=f[i], line = dict(width=3, color=color[i]), name='λ=' + str(l[i]), legendgroup=str(i))
    trace1 = go.Scatter(x=x, y=F[i], line = dict(width=3, color=color[i]), yaxis='y2', name='λ=' + str(l[i]), legendgroup=str(i), showlegend=False)
    fig.add_trace(trace0, row=1, col=1)
    fig.add_trace(trace1, row=2, col=1)

# サイズや凡例など全体的な設定
fig.update_layout(width=500, height=600, font=dict(family='Noto Sans'), showlegend=True, legend_orientation='h', legend=dict(x=0, y=-0.2), margin=dict(l=20, r=20, t=60, b=20))

# x軸の設定
fig.update_xaxes(title_text='$x$', ticks='outside', tickwidth=0.3, ticklen=0.4, gridwidth=0.2, range=[-0.1, 5.1], dtick=1, showline=True, linewidth=0.3, linecolor='black', row=1,col=1)
fig.update_xaxes(title_text='$x$', ticks='outside', tickwidth=0.3, ticklen=0.4, gridwidth=0.2, range=[-0.1, 5.1], dtick=1, showline=True, linewidth=0.3, linecolor='black', row=2,col=1)

# y軸の設定
fig.update_yaxes(ticks='outside', tickwidth=0.3, ticklen=0.4, gridwidth=0.5, showline=True, linewidth=0.3, linecolor='black', row=1, col=1)
fig.update_yaxes(ticks='outside', tickwidth=0.3, ticklen=0.4, gridwidth=0.5,range=[-0.1, 1.1], dtick=0.25, showline=True, linewidth=0.3, linecolor='black', row=2, col=1)

# 保存 ローカルに保存するときは上(もちろん公開されない)
# fig.write_html('exponential-distribution.html')
py.plot(fig, filename='exponential-distribution', auto_open=True)

グラフを作成するとChart Studio上に表示されるので、Public -> Embed -> iframe であとはコピペで埋め込みできる。

アニメーション

Plotlyの公式ドキュメントにあったものを参照し、アニメーションを作った。

カーソルを重ねるとデータが見れる上に、5年ごとのデータの遷移がわかる。
上のグラフのコードはこちら。
plotly.expressを使っているが、これはとても簡単に図を作成できるライブラリ。
ただ、こだわった図に拡張するのが少し難しい。

import plotly.express as px
import chart_studio
import chart_studio.plotly as py

# usernameとAPI keyを指定
chart_studio.tools.set_credentials_file(username='YOUR_NAME', api_key='YOUR_API_KEY')

df = px.data.gapminder()
fig = px.scatter(df, x="gdpPercap", y="lifeExp", animation_frame="year", animation_group="country", size="pop", color="continent", hover_name="country", log_x=True, size_max=55, range_x=[100,100000], range_y=[25,90])
py.plot(fig, filename='animation', auto_open=True)

3次元グラフ

インタラクティブなグラフで最も力を発揮するのは3次元グラフだと思う。
PDFのような静的な画像では利用者が好きな角度から見ることができない。

Plotlyの公式ドキュメントにあった例を参照して、3Dグラフを作ってみた。

同じようにカーソルをあわせるとデータが見えるだけではなく、掴んで回転させることができる。

上のコードはこちら。

import plotly.graph_objects as go
import chart_studio
import chart_studio.plotly as py
import pandas as pd

# usernameとAPI keyを指定
chart_studio.tools.set_credentials_file(username='YOUR_NAME', api_key='YOUR_API_KEY')

# データを取得
z_data = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv')

fig = go.Figure(data=[go.Surface(z=z_data.values)])
fig.update_layout(title='Mt Bruno Elevation', autosize=False, width=500, height=500, margin=dict(l=65, r=50, b=65, t=90))

py.plot(fig, filename='exponential-distribution', auto_open=True)

作ったグラフをiframeタグで埋め込む方法

iframeはHTMLファイルの中にHTMLファイルを埋め込むときにとてもよく使われる。
そもそもiframeとは?と思った方はこちらのサイトへどうぞ。

PlotlyではChartStudioからiframeタグをコピーすることができる。

iframeタグの場所は、まず載せたいグラフのVIEWページに行き、下の画像の右上にあるような「Public」をクリック。

そうすると、下の画像が出てくるので、「Embed」から「iframe」を選択してコピーするだけ。


それを好きなところに貼り付けるだけで、インタラクティブなグラフを表示することができる。

注意点

ちなみに、WordPressエディタにそのまま貼り付けるとfigureタグに変換されてしまい、とても見辛いグラフになるので注意する必要がある。
例えば、上の3次元グラフでは、

<iframe width="800" height="500" frameborder="0" scrolling="no" src="//plotly.com/~h-memo/29.embed?link=false"></iframe>

と入力しているのだが、そのままWordPressエディタに貼り付けると、次のコードに変換されてしまう。

<figure><iframe width="800" height="500" src="//plotly.com/~h-memo/29.embed?link=false"></iframe></figure>

この状態だと、次のように表示されてしまう。

枠線が生まれ、スクロールされるようになり、グラフを触りづらい。
したがって、そのまま貼り付ける前に段落を「カスタムHTML」に変換してから貼り付けるべきである。

また、デフォルトの状態だと、「EDIT CHART」というリンクが生成されるため邪魔である。
これを消すために ?link=false をsrcの部分に追加する必要がある。

最後に、図は中央揃えにしたいが「カスタムHTML」は「画像」ではないのでいつものようにボタン1つで中央揃えにできるUIが用意されていない。
したがって、自分自身で中央揃えにするコードを書く必要があり、次のように書けば良い。
これでもとの3次元グラフのような表示ができる。

<center>
<iframe width="800" height="500" frameborder="0" scrolling="no" src="//plotly.com/~h-memo/29.embed?link=false"></iframe>
</center>
スポンサーリンク
H-MEMO

コメント