Plotly

簡単な例

Plotly は対話型視覚化ライブラリである。中身はJavaScriptだがPythonやRなどで操作できる。

ここでは,私の平均身長の推移のデータをimabari_ehimeさんがPlotlyでグラフ化された平均身長の推移をplotlyでグラフ化という記事を参考にして,Plotlyを触ってみよう。

まずは pip install plotly などとしてインストールする。

import pandas as pd

pd.options.plotting.backend = "plotly"

df = pd.read_csv("https://okumuralab.org/~okumura/python/data/height.csv",
                 index_col=0)

fig = df[["男17歳", "男16歳", "男15歳"]].plot(markers=True)

ここまででは何も起こらない。ここで

fig.show()

と打ち込むと,http://127.0.0.1:53999 のようなアドレスがデフォルトのWebブラウザで開き,グラフが表示される。マウスで範囲指定すれば,その部分が拡大表示される。図をダブルクリック(スマホならダブルタップ)するか右上の「🏠 Reset axes」ボタンを押せば元のサイズに戻る。「📷 Download plot as a png」でPNG画像としてダウンロードできる。

対話型のままの図をWebで公開するには,いくつかの方法がある。まず

fig.write_html("fig.html")

で,スタンドアローンの巨大なHTMLファイルができる。

別ページにインクルードするための軽い図を出力するには,例えば

fig.write_html("fig.html", include_plotlyjs=False, full_html=False,
               default_width=800, default_height=600)

のようにする(default_width="100%" でブラウザの幅いっぱいの図になる)。これを別ページにコピペすればよい(あるいは何らかの方法でインクルードする)。別ページのヘッダには次の2行を入れておく:

<script>window.PlotlyConfig = {MathJaxConfig: 'local'};</script>
<script src="https://cdn.plot.ly/plotly-2.9.0.min.js"></script>

これを実際に行うと,次のようになる:

範囲指定したりして対話型に動作することを確認されたい。

Plotly Express

上と同じ図を Plotly Express折れ線グラフを使って描いてみよう:

import pandas as pd
import plotly.express as px

df = pd.read_csv("https://okumuralab.org/~okumura/python/data/height.csv")
fig = px.line(df, x='年度', y=["男17歳", "男16歳", "男15歳"], markers=True)
fig.write_html("fig.html", include_plotlyjs=False, full_html=False,
               default_width=800, default_height=600)

結果は上とほぼ同じなので省略する。

棒グラフの例として,毎日の東京都のCOVID-19感染確認者数:

import pandas as pd
import plotly.express as px

df = pd.read_csv("https://okumuralab.org/~okumura/python/data/COVID-tokyo.csv")
fig = px.bar(df.query('date >= "2022-01-01"'), x='date', y='confirmed')
fig.write_html("fig.html", include_plotlyjs=False, full_html=False,
               default_width=800, default_height=600)

棒の幅を丸一日(86400000ミリ秒)に広げたいときは fig = ... の次に fig.update_traces(width=86400000) を入れる。

図のJavaScript部分を切り出して別ファイルにする

fig.write_html() が吐き出すHTMLは <div id="..." class="plotly-graph-div" style="height:600px; width:800px;"></div> のような図の入れ場所以外はJavaScriptコードなので,これらを分離すれば,インクルードがより簡単にできる。

具体的には,例えば次のようにする:

import re

(グラフを描く部分は略)

fig.write_html("fig.html", include_plotlyjs=False, full_html=False,
               default_width=800, default_height=600, div_id="plotly_ex1")

with open("fig.html") as f:
    text = f.read()
m = re.search('(<div id="(.*?)".*?</div>) *<script type="text/javascript"> *(.*) *</script>',
              text)
if m:
    div = m[1]
    id = m[2]
    js = m[3]
    js = re.sub("      *", "\n", js)
    print(div)
    print('<script src="js/' + id +'.js"></script>')
    with open(id + ".js", "w") as f:
        f.write(js)

標準出力に出力される2行だけをHTMLにコピペし,ファイルとして出力されるJavaScriptコードを js/ サブディレクトリに入れる。最終的にこのページはそのようにして作った。

なお,style="height:600px; width:800px;" の代わりに style="max-width:100%" とするとブラウザの幅になる。自殺統計の図はそのようにした。どちらが使いやすいであろうか。


Last modified: