9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

plotly スライダーを使ったグラフの応用

Last updated at Posted at 2020-11-01

はじめに

plotlyでスライダー付きグラフをよく作成するのでメモです。

1つのプロットをスライダーで動かすのは公式にコードが乗っているので、複数同時に動かしたい時などのちょっとした応用を記載します。

公式サイト(スライダーの説明ページ)
Sliders | Python | Plotly

環境

Mac OS
python 3.8.5
plotly 4.12.0

pip, import

pipから以下をインストールします。記事でnumpyを使用する為一緒にインストールしています。

pip install plotly
pip install numpy
import numpy as np
import plotly.offline as offline
import plotly.graph_objs as go

plotly スライダーの基本

公式にも載っていますが、一応

See the Pen simple slider by shunta-m (@shunta-m) on CodePen.

trace(プロット)作成 -> レイアウト作成 -> グラフ作成の順で書いています

import numpy as np
import plotly.offline as offline
import plotly.graph_objs as go

# プロットを保存するリスト
data = []
x = np.linspace(0, 10, 101)
# プロットの作成
# 0, 0.1, ... , 5までのプロットを作成する
for step in np.linspace(0, 5, 51):
    y = np.sin(step * x)

    trace = go.Scatter(
        x=x,
        y=y,
        name="sin step{:.1f}".format(step),
        line=dict(color="red", width=3),
        visible=False, )  # 見えない状態にする
    data.append(trace)

# 初期状態として、10番目のプロットを見えるようにしておく
data[10].visible = True

# スライダーの位置によってどこを表示/非表示にするかを保存するリスト
steps = []
"""
for文内でどこを見えるようにするか決めている
例えばスライダーが10にいる時、10番目のプロットが見えればいいので
一度全てを非表示 -> 10番目プロットのvisibleをTrueにして見えるようにする
"""
for s in range(len(data)):
    step = dict(method="update",
                args=[{"visible": [False] * len(data)},  # 一度全て非表示
                      {"title": "Simple slider step: {}".format(s)}]  # スライダーの位置によってタイトルも変更する
                )
    step["args"][0]["visible"][s] = True  # 対応するものだけを見えるようにする
    # ↑で作ったs番目だけが見えるレイアウトをstepsに追加
    steps.append(step)

sliders = [dict(
    active=10,  # スライダーの初期値
    currentvalue=dict(prefix="Frequency: "),
    pad=dict(t=50),  # スライダーの占有範囲, 数値を大きくする程スライダーの範囲が大きくなる
    steps=steps)]  # stepsが持っている表示/非表示の情報を使う

layout = go.Layout(
    title="Simple slider step: 10",  # 初期状態のタイトル
    xaxis=dict(title="x"),
    yaxis=dict(title="y"),
    font=dict(family="Meiryo", size=16),  # グラフ内のフォントをメイリオ、サイズを16へ
    # ホバーモード(グラフにカーソルを近づけた時の数値の見え方)の設定
    # 与えることができる文字列は "x", "y", "closest", False, "x unified", "y unified"
    hovermode="x unified",
    hoverlabel=dict(font_size=16),  # ホバーモードの文字サイズ設定
    sliders=sliders,  # スライダー追加
    showlegend=True)  # 凡例表示をTrueに

fig = dict(data=data, layout=layout)

# 出力
offline.plot(fig, auto_open=True, include_plotlyjs="cdn", filename="simple_slider.html")

複数プロットを動かす

sin波、cos波を両方動かしてみます。

plots.gif

import numpy as np
import plotly.offline as offline
import plotly.graph_objs as go

# sin, cos波のtraceをを別々に保存
sin_data, cos_data = [], []
x = np.linspace(0, 10, 101)

for step in np.linspace(0, 5, 51):
    y = np.sin(step * x)
    y2 = np.cos(step * x)

    sin_trace = go.Scatter(
        x=x,
        y=y,
        name="sin {:.1f}Hz".format(step),
        line=dict(color="red", width=3),
        visible=False, )

    cos_trace = go.Scatter(
        x=x,
        y=y2,
        name="cos {:.1f}Hz".format(step),
        line=dict(color="blue", width=3),
        visible=False, )

    sin_data.append(sin_trace)
    cos_data.append(cos_trace)

sin_data[10].visible = True
cos_data[10].visible = True

data = sin_data + cos_data

steps = []
"""
sin_data, cos_dataの表示/非表示を別々に設定した後、結合してvisibleキーに追加
例えばスライダーが2の時、
sin_visible = [False, False, True, False,...]
cos_visible = [False, False, True, False,...]
にした後2つを結合することで、sin, cos共に2番地目のtraceを表示できるようにする
"""
for s in range(len(sin_data)):
    # sin_data, cos_data共に一度全て非表示にする
    sin_visible, cos_visible = [False] * len(sin_data), [False] * len(cos_data)
    # それぞれs番目だけ見えるようにする
    sin_visible[s], cos_visible[s] = True, True
    step = dict(method="update",
                args=[{"visible": sin_visible + cos_visible},
                      {"title": "Simple slider step: {}".format(s)}]
                )
    steps.append(step)

sliders = [dict(
    active=10,
    currentvalue=dict(prefix="Frequency: "),
    pad=dict(t=50),
    steps=steps)]

layout = go.Layout(
    title="Simple slider step: 10",
    xaxis=dict(title="x"),
    yaxis=dict(title="y"),
    font=dict(family="Meiryo", size=16),
    hovermode='x unified',
    hoverlabel=dict(font_size=16),
    sliders=sliders,
    showlegend=True)

fig = dict(data=data, layout=layout)

offline.plot(fig, include_plotlyjs="cdn", filename="plots.html")

一部プロットを動かす

同じグラフ内にスライダーで動かしたいもの、動かしたくないものがある時

plots2.gif

import numpy as np
import plotly.offline as offline
import plotly.graph_objs as go

data = []
sin_data, cos_data = [], []
x = np.linspace(0, 10, 101)

# 固定プロット
trace = go.Scatter(
    x=x,
    y=2 * np.cos(x),
    name="2 * cos",
    line=dict(color="green", width=3),
    visible=True, )
data.append(trace)  # dataの0番目が固定プロット情報

# スライダープロット
for step in np.linspace(0, 5, 51):
    y = np.sin(step * x)
    y2 = np.cos(step * x)
    sin_trace = go.Scatter(
        x=x,
        y=y,
        name="sin {:.1f}Hz".format(step),
        line=dict(color="red", width=3),
        visible=False, )

    cos_trace = go.Scatter(
        x=x,
        y=y2,
        name="cos {:.1f}Hz".format(step),
        line=dict(color="blue", width=3),
        visible=False, )

    sin_data.append(sin_trace)
    cos_data.append(cos_trace)

sin_data[10].visible = True
cos_data[10].visible = True

data += sin_data + cos_data
steps = []
"""
固定プロットは常に表示すればいいので、visibleを常にTrueにする
    ->dataの0番目(固定プロット)をTrueにする
"""
for s in range(len(sin_data)):
    sin_visible, cos_visible = [False] * len(sin_data), [False] * len(cos_data)
    sin_visible[s], cos_visible[s] = True, True
    step = dict(method="update",
                args=[{"visible": [True] + sin_visible + cos_visible},  # 0番目は常にTrue
                      {"title": "Simple slider step: {}".format(s)}]
                )
    steps.append(step)

sliders = [dict(
    active=10,
    currentvalue=dict(prefix="Frequency: "),
    pad=dict(t=50),
    steps=steps)]

layout = go.Layout(
    title="Simple slider step: 10",
    xaxis=dict(title="x"),
    yaxis=dict(title="y"),
    font=dict(family="Meiryo", size=16),
    hovermode='x unified',
    hoverlabel=dict(font_size=16),
    sliders=sliders,
    showlegend=True)

fig = dict(data=data, layout=layout)

offline.plot(fig, include_plotlyjs="cdn", filename="plot2.html")

途中から非表示にする

スライダーが40以上になるとcosが消えます。

plots3.gif

単純に40以上の時cos_traceのx, yの値をNoneにしています。

import numpy as np
import plotly.offline as offline
import plotly.graph_objs as go

x = np.linspace(0, 10, 101)

data = []
sin_data, cos_data = [], []

trace = go.Scatter(
    x=x,
    y=2 * np.cos(x),
    name="2 * cos",
    line=dict(color="green", width=3),
    visible=True, )
data.append(trace)

for step in np.linspace(0, 5, 51):
    y = np.sin(step * x)
    y2 = np.cos(step * x)
    sin_trace = go.Scatter(
        x=x,
        y=y,
        name="sin {:.1f}Hz".format(step),
        line=dict(color="red", width=3),
        visible=False, )

    if step < 4:
        cos_trace = go.Scatter(
            x=x,
            y=y2,
            name="cos {:.1f}Hz".format(step),
            line=dict(color="blue", width=3),
            visible=False, )
    else:
        cos_trace = go.Scatter(x=None, y=None)  # 4以上はNone

    sin_data.append(sin_trace)
    cos_data.append(cos_trace)

sin_data[10].visible = True
cos_data[10].visible = True

data += sin_data + cos_data

steps = []
for s in range(len(sin_data)):
    sin_visible, cos_visible = [False] * len(sin_data), [False] * len(cos_data)
    sin_visible[s], cos_visible[s] = True, True
    step = dict(method="update",
                args=[{"visible": [True] + sin_visible + cos_visible},
                      {"title": "Simple slider step: {}".format(s)}]
                )
    steps.append(step)

sliders = [dict(
    active=10,
    currentvalue=dict(prefix="Frequency: "),
    pad=dict(t=50),
    steps=steps)]

layout = go.Layout(
    title="Simple slider step: 10",
    xaxis=dict(title="x"),
    yaxis=dict(title="y"),
    font=dict(family="Meiryo", size=16),
    hovermode='x unified',
    hoverlabel=dict(font_size=16),
    sliders=sliders,
    showlegend=True)

fig = dict(data=data, layout=layout)

offline.plot(fig, include_plotlyjs="cdn", filename="plots3.html")

参考サイト

公式サイト
Plotly Python Graphing Library | Python | Plotly

codepen
Plotlyを使った描画結果をQiita内にCodePen埋め込むことで確認する - Qiita
Qiitaで記事にCodePenが埋め込めるようになりました - Qiita

9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?