Python
plotly

[Python] Plotlyでぐりぐり動かせるグラフを作る

More than 1 year has passed since last update.

はじめに

Pythonから利用できるライブラリ、Plotlyの初歩的な使い方を記述します。
リンク先のサンプルを見るとわかるように、Plotlyを用いると、非常に多くの種類の、ぐりぐり動かせるグラフを作ることができます。

なお、Plotlyには、作成したグラフをWeb上で編集したり、公開したりできる機能がありますが、
今回はすべてローカルで実行することとします。

実行環境

  • Windows 10
  • Python 3.5.2(Anaconda)
  • Jupyter notebook

インストール

pip install plotlyでPlotlyをインストールします。

データの取り込み

例として、Wikipediaから拾ってきた、日本の年ごとの出生数と出生率のデータをグラフ化してみます。
下記データをbirth.csvとしたものを、Jupyterのファイルと同一フォルダに置きます。

year,bitrhs,birth rate
2000,1190547,1.36
2001,1170662,1.33
2002,1153855,1.32
2003,1123610,1.29
2004,1110721,1.29
2005,1062530,1.26
2006,1092674,1.32
2007,1089818,1.34
2008,1091156,1.37
2009,1070035,1.37
2010,1071304,1.39
2011,1050806,1.39
2012,1037101,1.41
2013,1029816,1.43
2014,1003532,1.42
2015,1005656,1.46

データの取り込みや操作には、Pandasを用いると便利です。
Pandasは、Anacondaをインストールすると自動的に入っています。

import pandas as pd
raw = pd.read_csv("birth.csv")

グラフの作成

初期化

まず、Jupyter内部でプロットするために、下記コードを実行します。Jupyter内部で表示しない場合には不要です。
引数にある、connectedTrueにすると、PlotlyのJavascriptをインターネットから取得するようになります。

import plotly
plotly.offline.init_notebook_mode(connected=False)

プロットするデータの指定

続いて、プロットするデータを指定します。
今回、出生数は棒グラフ、出生率は折れ線グラフで表現します。
dataという配列を用意し、棒グラフだったらplotly.graph_objs.Bar
折れ線グラフだったらplotly.graph_objs.Scatterに、X軸やY軸のデータ、系列名を指定します。
yaxis="y2"と指定することで、第2軸にプロットすることができます。

data = [
    plotly.graph_objs.Bar(x=raw["year"], y=raw["births"], name="Births"),
    plotly.graph_objs.Scatter(x=raw["year"], y=raw["birth rate"], name="Birth Rate", yaxis="y2")
]

グラフレイアウトの指定

次に、グラフのレイアウトを指定します。グラフのタイトルや、凡例の位置、第2軸を設定します。

layout = plotly.graph_objs.Layout(
    title="Births and Birth Rate in Japan",
    legend={"x":0.8, "y":0.1},
    xaxis={"title":"Year"},
    yaxis={"title":"Births"},
    yaxis2={"title":"Birth Rate", "overlaying":"y", "side":"right"},
)

プロット

Jupyter内で表示したい場合には、iplotを呼んで、グラフを作成します。
Jupyter外部で表示する場合や、HTMLを作成したい場合には、plotを呼びます。オプションでファイル名を指定しない場合には、同一フォルダにtemp-plot.htmlが作成されます。

fig = plotly.graph_objs.Figure(data=data, layout=layout)
plotly.offline.iplot(fig)
#plotly.offline.plot(fig)

こんな感じのグラフが出来上がります。
aa.gif

簡単な操作方法はこちら

  • グラフ内でドラッグすると、X軸方向、Y軸方向、矩形に拡大
  • X軸、Y軸上でドラッグすると、軸方向に移動
  • ダブルクリックすると、初期表示に戻る
  • ツールバーのボタンを押して画像として保存

その他オプション

グラフエリアの大きさ

layout = plotly.graph_objs.Layout(
    width=800, height=600,
)

軸の最大値最小値

単に最大最小値を設定する場合は、axisrangeオプションを指定します。
ゼロから目盛りを始めたい場合や、負数を表示したくない場合には、
rangemodeオプションに"tozero""nonnegative"を指定します。

layout = plotly.graph_objs.Layout(
    xaxis={"title":"Year", "range": [2010, 2016]}, #from year 2010 to 2016
    yaxis={"title":"Births", "rangemode":"tozero"}, #starts from zero
)

フォント

font-familyはCSSで指定するのと同じようにします。

layout = plotly.graph_objs.Layout(
    font={"family":"Yu Gothic Bold, sans-selif", "size":20},
)

そのほか

そのほか、Plotlyでは細かい部分まで指定することができます。
これらオプションについては、Plotlyのサイトを見たり、googleで検索してみましょう。

ツールバーの不要なボタンや「Edit in Plotly」の削除

ローカル外に漏らしたくないデータの場合、作成したグラフに、「Save and edit plot in cloud」や「Ploduced with Plotly」のボタンや、「Export to plot.ly」のリンクが存在するのは、気持ちのいいものではないです。そこで、これらを表示させないようにします。

buttons.png

まず、プロット時にshow_link=Falseを指定することで、「Export to plot.ly」を消すことができます。

plotly.offline.iplot(fig, show_link=False)
#plotly.offline.plot(fig, show_link=False)

一方、ツールバーのボタンの表示を消すオプションは、StackOverflowの投稿関連するプルリクエストがマージされていない状況を見る限り、存在しないようです。そこで、init_notebook_modeで読み込まれる、Plotlyのフォルダ内のplotly.min.jsを編集する方法をとります。
いつの間にかiplotの引数で渡せるようになっていました。

plotly.offline.iplot(fig, show_link=False, config={"displaylogo":False, "modeBarButtonsToRemove":["sendDataToCloud"]})

とすることで、消すことができます。

PandasのDataframeのプロット

Cufflinksというライブラリを利用すると、df.iplot()と書くだけでDataframeのPlotlyのグラフを描くことができます。
[Python] CufflinksでPandasのデータフレームをPlotlyに一発描画を参照ください。

matplotlibのPlotly化

matplotlib.pyplotで書いたグラフを、iplot_mpl(fig)と打つだけでPlotlyのインタラクティブなグラフへ変更することができます。

import matplotlib.pyplot as plt
import plotly.offline

plotly.offline.init_notebook_mode()

fig = plt.figure()
plt.plot([1,3,4,2,1,3])
plotly.offline.iplot_mpl(fig)

ただ、凡例を入れたい場合にはひと手間加える必要があるなど、まだ開発途中といったところでしょうか。

import matplotlib.pyplot as plt
import plotly.offline
import plotly.tools

plotly.offline.init_notebook_mode()

fig = plt.figure()
plt.plot([1,3,4,2,1,3], label="legend")
plt.title("title")
# plt.legend()は要らない
plotly_fig = plotly.tools.mpl_to_plotly( fig )
plotly_fig['layout']['showlegend'] = True
plotly.offline.iplot(plotly_fig, show_link=False)

(ひとまず折れ線グラフを描きたいときのコピペ用)

import plotly
plotly.offline.init_notebook_mode()
data = [
    plotly.graph_objs.Scatter(y=[2,3,1,2,5,2], name="legend"),
    plotly.graph_objs.Scatter(x=[1,2,3,4,5,6], y=[1,2,3,2,3,1], name="legend2"),
]
layout = plotly.graph_objs.Layout(
    title="title",
    xaxis={"title":"xlabel"},
    yaxis={"title":"ylabel"},
)
fig = plotly.graph_objs.Figure(data=data, layout=layout)
plotly.offline.iplot(fig, show_link=False)