カテゴリー

Plotly全般

【plotly&スライダー】plotlyのslidersにスライダーを追加

2021年4月24日

こんな人にオススメ

plotlyではグラフにスライダーをつけることができるらしいけど、どうやって追加するの?

ということで、今回はplotlyにスライダー機能を追加する方法を解説する。この機能を使用することで、変数などの流れが見やすくなる。

plotlyではボタンの機能が有名だけど、スライダーはボタンをスライド方式にしただけ。ほぼほぼ書き方はボタンと同じ。ボタン自体とボタンとスライダーの比較記事は以下。

【plotly&ボタン】plotlyのupdatemenusにbuttonsを追加

こんな人にオススメ plotlyって| ...

続きを見る

【plotly&ボタンとスライダー】goとpxでのupdatemenusとsliders

こんな人にオススメ plotlyってgo ...

続きを見る

なお、Plotly公式の「Sliders in Python」にスライダーの描き方が書かれているが、goとpxで1グラフずつしか解説されていない。

本記事でスライダーのコードを分解しながら解説するので、この機会にスライダーに対する理解を深めてくれたら幸いだ。

python環境は以下。

  • Python 3.10.1
  • numpy 1.21.4
  • plotly 5.4.0
  • plotly-orca 3.4.2

運営者のメガネです。YouTubeTwitterInstagramも運営してます。

自己紹介はこちらから、お問い合わせはこちら。

運営者メガネ

作成したコード全文

下準備(import

import copy
import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

まずは下準備としてのimport関連。今回はplotlygoの散布図go.Scatterを使用して解説する。copynumpyについてはデータの作成などに使用する。pioplotlyのグラフ保存に使用する。

go.Scatterpioについては以下参照。

【plotly&go.Scatter】plotlyの散布図グラフの描き方

こんな人にオススメ plotlyのと{ ...

続きを見る

plotlyでグラフを静止画として保存する際に出るポップアップ
【plotly&orca】plotlyで静止画保存(orca)

こんな人にオススメplotlyで画ࠔ ...

続きを見る

スライダーなしのグラフ


まずはスライダーなしのグラフから。今回はy = x + aの1次関数で切片のaを変えながらグラフを作成した。

全プロットをそのままプロットしているので、もちろん3つのプロットが表示される。

import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# 3つのグラフをシンプルにグラフ化

x = np.arange(5)
y0 = x + 0
y1 = x + 1
y2 = x + 2

# 配列の要素にプロット内容を格納
plot = [
    go.Scatter(x=x, y=y0, name='y0'),
    go.Scatter(x=x, y=y1, name='y1'),
    go.Scatter(x=x, y=y2, name='y2'),
]
# レイアウトの作成
layout = go.Layout(
    font_size=20,  # グラフ全体のフォントサイズ
    hoverlabel_font_size=20  # ホバーのフォントサイズ
)
# グラフの表示
fig = go.Figure(data=plot, layout=layout)
fig.show()

# グラフ保存
prefix = 'plotly-slider'  # 保存ファイル名の接頭辞
save_name = f"{prefix}_simple"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html")
pio.write_image(fig, f"{save_name}.png")

グラフにスライダーを設置


続いてはスライダーを追加。スライダーの内容は切片の値にしたので、スライダーの各ステップは3つにした。この3ステップを行き来することでプロットを切り替えるように設定。

まずは全体コードを載せてから、スライダー部分について解説する。

import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# グラフにスライダーを設置

x = np.arange(5)
y0 = x + 0
y1 = x + 1
y2 = x + 2

# 配列の要素にプロット内容を格納
plot = [
    go.Scatter(x=x, y=y0, name='y0'),
    go.Scatter(x=x, y=y1, name='y1'),
    go.Scatter(x=x, y=y2, name='y2'),
]

# y0表示用のステップ作成
step0 = dict(
    label=0,  # スライダーのラベル
    method='update',  # スライダーの適用範囲はデータプロットとレイアウト
    args=[
        dict(visible=[True, False, False]),  # y0のみ表示
        dict(title='y = x + 0'),  # グラフタイトル
    ]
)
# y1表示用のステップ作成
step1 = dict(
    label=1,  # スライダーのラベル
    method='update',  # スライダーの適用範囲はデータプロットとレイアウト
    args=[
        dict(visible=[False, True, False]),  # y1のみ表示
        dict(title='y = x + 1'),  # グラフタイトル
    ]
)
# y2表示用のステップ作成
step2 = dict(
    label=2,  # スライダーのラベル
    method='update',  # スライダーの適用範囲はデータプロットとレイアウト
    args=[
        dict(visible=[False, False, True]),  # y2のみ表示
        dict(title='y = x + 2'),  # グラフタイトル
    ]
)

# スライダーをひとまとめにする
steps = [step0, step1, step2]

# レイアウトに設置するためのスライダー作成
sliders = [
    dict(
        active=0,  # 初期状態で表示するプロットのインデックス
        # 各スライダーの傾きをスライダーの上に表示
        currentvalue=dict(prefix='切片 = '),
        steps=steps,
    )
]

# レイアウトの作成
layout = go.Layout(
    font_size=20,  # グラフ全体のフォントサイズ
    hoverlabel_font_size=20,  # ホバーのフォントサイズ
    yaxis_range=(0, 8),  # 縦軸の表示範囲
    sliders=sliders  # スライダーを設置
)
# グラフの表示
fig = go.Figure(data=plot, layout=layout)
fig.show()

# グラフ保存
prefix = 'plotly-slider'  # 保存ファイル名の接頭辞
save_name = f"{prefix}_slider"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html")
pio.write_image(fig, f"{save_name}.png")

各スライダー(step0, step1, step2)の内容を設定

# y0表示用のステップ作成
step0 = dict(
    label=0,  # スライダーのラベル
    method='update',  # スライダーの適用範囲はデータプロットとレイアウト
    args=[
        dict(visible=[True, False, False]),  # y0のみ表示
        dict(title='y = x + 0'),  # グラフタイトル
    ]
)
# y1表示用のステップ作成
step1 = dict(
    label=1,  # スライダーのラベル
    method='update',  # スライダーの適用範囲はデータプロットとレイアウト
    args=[
        dict(visible=[False, True, False]),  # y1のみ表示
        dict(title='y = x + 1'),  # グラフタイトル
    ]
)
# y2表示用のステップ作成
step2 = dict(
    label=2,  # スライダーのラベル
    method='update',  # スライダーの適用範囲はデータプロットとレイアウト
    args=[
        dict(visible=[False, False, True]),  # y2のみ表示
        dict(title='y = x + 2'),  # グラフタイトル
    ]
)

まずはスライダーの設定から。今回は3種類のスライダーのステップを作成。主に使用する引数は以下。

  • label: スライダーに表示されるボタンラベル
  • method: クリック時にどの部分を変更するか
    • 'restyle' : プロットだけ変更
    • 'relayout': レイアウトだけ変更
    • 'animate': アニメーションにする
    • 'update': プロットとレイアウト両方を変更
    • 'skip': 変更しない
  • args: クリック時の動作
    • 1つ目のdictがプロット関連
    • 2つ目のdictがレイアウト関連

今回はlabelを切片の値0, 1, 2に設定した。methodはプロットを表示・非表示させるvisibleと、グラフタイトルtitleを使うために’update’に。

あとはargsでプロット関連とレイアウト関連の設定を行えばいい。分解してみると結構簡単に見える。

visibleの順番はプロットするデータの順番と同じ。今回だと変数plotにy = x + 0, y = x + 1, y = x + 2の順番で格納したので、[True, False, False]にすると初めのy = x + 0だけが表示、その他は非表示になる。

使用するスライダーを全て配列にまとめる

# スライダーをひとまとめにする
steps = [step0, step1, step2]

これに関してはシンプルに、作成したスライダーのステップたちを1つの配列にまとめるだけ。今回は3つのステップを作成したのでこれらをひとまとめにした。

レイアウトにスライダーを設置するための設定

# レイアウトに設置するためのスライダー作成
sliders = [
    dict(
        active=0,  # 初期状態で表示するプロットのインデックス
        # 各スライダーの傾きをスライダーの上に表示
        currentvalue=dict(prefix='切片 = '),
        steps=steps,
    )
]

続いてはレイアウトにスライダーを設置するための設定。各ステップではなく、作成したスライダー全体をどうやってレイアウトに反映させるかってこと。主な引数は以下。

  • active: グラフ作成時に見た目上どのボタンが押されているか
  • currentvalue: 各スライダーのステップを表示する際の設定。prefixは接頭辞
  • len: スライダーの長さ。デフォルトは1
  • x, y: ボタンの位置
  • xanchor, yanchor: x, yの基準。x=1, xanchor=’right’ならボタン右端がx=1にくる
  • steps: 作成したステップはここへ
  • pad: 余白。t, b, l, rと数値で上下左右の余白を設定

activeはグラフの初期表示時にどのステップが見た目の上で選択されているかを決める。

これは見た目上の話で、例えばグラフは全グラフを表示しているが、active=0y0のボタンが押されるようにするとおかしなことになる。上のグラフがそう。

なお、ボタンの場合はactive=-1と指定することでボタンを押していない状態を再現できたが、スライダーは1以上の整数値じゃないといけない。

グラフレイアウトの引数slidersに設定を適用

# レイアウトの作成
layout = go.Layout(
    font_size=20,  # グラフ全体のフォントサイズ
    hoverlabel_font_size=20,  # ホバーのフォントサイズ
    yaxis_range=(0, 8),  # 縦軸の表示範囲
    sliders=sliders  # スライダーを設置
)

最後に作成したスライダー設定をレイアウトに反映させる。引数はsliders。今回はボタン設定の変数もslidersで作成したので、sliders=slidersとなる。

その他の引数についてはコメントアウトの通り。グラフタイトルとフォントサイズを変更、スライダーで縦軸が自動で変わるのを防ぐために縦軸の表示範囲を固定している。

もし、縦軸の表示範囲を固定していなかったら、スライダーで表示されるプロットの値に応じて自動で範囲が変わってしまう。そうなるとグラフの見た目が同じに見えてしまう。これを防ぐためにrangeを設定。

forを使用してスライダーを作成


先程はスライダーのステップを1つずつ作成した。ただ、これだと多数のステップがあるスライダーを設定する際に困る。

ということで、ここではforを使ってステップを作成する。できるグラフは同じになるので、スライダーの長さを変更しておいた。

import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# forを使ってスライダーを作成

x = np.arange(5)
y0 = x + 0
y1 = x + 1
y2 = x + 2

# 配列の要素にプロット内容を格納
plot = [
    go.Scatter(x=x, y=y0, name='y0'),
    go.Scatter(x=x, y=y1, name='y1'),
    go.Scatter(x=x, y=y2, name='y2'),
]

# スライダーの内容作成
steps = []
for num, _ in enumerate(plot):
    # 一旦全てのプロットを非表示にしてから、該当するプロットを表示に変更
    visible = [False] * len(plot)
    visible[num] = True

    step = dict(
        label=num,  # スライダーのラベル
        method='update',  # スライダーの適用範囲はデータプロットとレイアウト
        args=[
            dict(visible=visible),  # y0のみ表示
            dict(title=f"y = x + {num}"),  # グラフタイトル
        ]
    )
    steps.append(step)

# レイアウトに設置するためのスライダー作成
sliders = [
    dict(
        active=0,  # 初期状態で表示するプロットのインデックス
        # 各スライダーの傾きをスライダーの上に表示
        currentvalue=dict(prefix='切片 = '),
        steps=steps,
        len=0.5,  # スライダーの長さ
    )
]

# レイアウトの作成
layout = go.Layout(
    font_size=20,  # グラフ全体のフォントサイズ
    hoverlabel_font_size=20,  # ホバーのフォントサイズ
    yaxis_range=(0, 8),  # 縦軸の表示範囲
    sliders=sliders  # スライダーを設置
)
# グラフの表示
fig = go.Figure(data=plot, layout=layout)
fig.show()

# グラフ保存
prefix = 'plotly-slider'  # 保存ファイル名の接頭辞
save_name = f"{prefix}_slider_for"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html")
pio.write_image(fig, f"{save_name}.png")

10データのグラフで少し応用


ということで、これでスライダーの基礎は終わったんだが、少しデータ量の多いグラフで応用を効かせてみる。

ここではdictysで縦軸の配列を作成、各プロットの色も変数colorsで指定。色の反映はgo.Scatterの引数markerの引数colorで変更可能だが、マジックアンダースコア_marker_colorと省略している。

なお、go.Scatterの引数showlegend=Trueとすることで、プロットが1種類になっても凡例を残す事ができる。

import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# 10データのグラフで少し応用

x = np.arange(-3, 3 + 1)
ys = {}
for num in range(10):
    y = num * x  # y = axの形
    ys[f"{num}x"] = y
print(ys)
# {'0x': array([0, 0, 0, 0, 0, 0, 0]), '1x': array([-3, -2, -1,  0,  1,  2,  3]), '2x': array([-6, -4, -2,  0,  2,  4,  6]), '3x': array([-9, -6, -3,  0,  3,  6,  9]), '4x': array([-12,  -8,  -4,   0,   4,   8,  12]), '5x': array([-15, -10,  -5,   0,   5,  10,  15]), '6x': array([-18, -12,  -6,   0,   6,  12,  18]), '7x': array([-21, -14,  -7,   0,   7,  14,  21]), '8x': array([-24, -16,  -8,   0,   8,  16,  24]), '9x': array([-27, -18,  -9,   0,   9,  18,  27])}

# 各プロットの色
colors = (
    'red', 'blue', 'green', 'orange', 'black',
    'deeppink', 'purple', 'olive', 'deepskyblue', 'violet'
)

# 配列の要素にプロット内容を格納
plot = []
for num, (name, y) in enumerate(ys.items()):
    d = go.Scatter(
        x=x, y=y, name=name,
        marker_color=colors[num],  # プロット線の色
        showlegend=True  # 凡例を常に表示
    )
    plot.append(d)

# スライダーの内容作成
steps = []
for num, _ in enumerate(plot):
    # 一旦全てのプロットを非表示にしてから、該当するプロットを表示に変更
    visible = [False] * len(plot)
    visible[num] = True

    step = dict(
        label=num,  # スライダーのラベル
        method='update',  # スライダーの適用範囲はデータプロットとレイアウト
        args=[
            dict(visible=visible),  # y0のみ表示
            dict(title=f"y = {num}x"),  # グラフタイトル
        ]
    )
    steps.append(step)

# レイアウトに設置するためのスライダー作成
sliders = [
    dict(
        active=0,  # 初期状態で表示するプロットのインデックス
        # 各スライダーの傾きをスライダーの上に表示
        currentvalue=dict(prefix='傾き = '),
        steps=steps,
        # len=0.5,  # スライダーの長さ
    )
]

# レイアウトの作成
layout = go.Layout(
    font_size=20,  # グラフ全体のフォントサイズ
    hoverlabel_font_size=20,  # ホバーのフォントサイズ
    yaxis_range=(-30, 30),  # 縦軸の表示範囲
    sliders=sliders  # スライダーを設置
)
# グラフの表示
fig = go.Figure(data=plot, layout=layout)
fig.show()

# グラフ保存
prefix = 'plotly-slider'  # 保存ファイル名の接頭辞
save_name = f"{prefix}_10data"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html")
pio.write_image(fig, f"{save_name}.png")

グラフ作成時に初期グラフだけ表示


さっきのグラフだと初期表示で全グラフが表示されている。スライダーは0以上のステップしか使用できないからこれは不自然。

0を全プロット表示に設定しておけばいいんだけど、そうするとステップをまた作らないといけないからダルい。

という事で、以下のように一旦、全てのプロットの表示をvixsible=Falseにして非表示にし、その後に該当するプロットのだけvisible=Trueで表示にした。

import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# 配列の要素にプロット内容を格納
plot = []
for num, (name, y) in enumerate(ys.items()):
    d = go.Scatter(
        x=x, y=y, name=name,
        marker_color=colors[num],  # プロット線の色
        showlegend=True,  # 凡例を常に表示
        visible=False  # グラフを非表示に
    )
    plot.append(d)

# 0番目(y = 0x)のグラフだけ、後からvisible=Trueにして表示する
plot[0]['visible'] = True

また、初期グラフのタイトルもこれに合わせてy = 0xに変更した。スライダーを動かせば各ステップで設定したレイアウトが反映されるが、初めはレイアウトで指定する必要がある。

# レイアウトの作成
layout = go.Layout(
    font_size=20,  # グラフ全体のフォントサイズ
    hoverlabel_font_size=20,  # ホバーのフォントサイズ
    title='y = 0x',
    yaxis_range=(-30, 30),  # 縦軸の表示範囲
    sliders=sliders  # スライダーを設置
)

最終的なコードは以下。

import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# グラフ作成時に初期グラフだけ表示する

x = np.arange(-3, 3 + 1)
ys = {}
for num in range(10):
    y = num * x  # y = axの形
    ys[f"{num}x"] = y

# 各プロットの色
colors = (
    'red', 'blue', 'green', 'orange', 'black',
    'deeppink', 'purple', 'olive', 'deepskyblue', 'violet'
)

# 配列の要素にプロット内容を格納
plot = []
for num, (name, y) in enumerate(ys.items()):
    d = go.Scatter(
        x=x, y=y, name=name,
        marker_color=colors[num],  # プロット線の色
        showlegend=True,  # 凡例を常に表示
        visible=False  # グラフを非表示に
    )
    plot.append(d)

# 0番目(y = 0x)のグラフだけ、後からvisible=Trueにして表示する
plot[0]['visible'] = True

# スライダーの内容作成
steps = []
for num, _ in enumerate(plot):
    # 一旦全てのプロットを非表示にしてから、該当するプロットを表示に変更
    visible = [False] * len(plot)
    visible[num] = True

    step = dict(
        label=num,  # スライダーのラベル
        method='update',  # スライダーの適用範囲はデータプロットとレイアウト
        args=[
            dict(visible=visible),  # y0のみ表示
            dict(title=f"y = {num}x"),  # グラフタイトル
        ]
    )
    steps.append(step)

# レイアウトに設置するためのスライダー作成
sliders = [
    dict(
        active=0,  # 初期状態で表示するプロットのインデックス
        # 各スライダーの傾きをスライダーの上に表示
        currentvalue=dict(prefix='傾き = '),
        steps=steps,
    )
]

# レイアウトの作成
layout = go.Layout(
    font_size=20,  # グラフ全体のフォントサイズ
    hoverlabel_font_size=20,  # ホバーのフォントサイズ
    title='y = 0x',
    yaxis_range=(-30, 30),  # 縦軸の表示範囲
    sliders=sliders  # スライダーを設置
)
# グラフの表示
fig = go.Figure(data=plot, layout=layout)
fig.show()

# グラフ保存
prefix = 'plotly-slider'  # 保存ファイル名の接頭辞
save_name = f"{prefix}_10data_ini"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html")
pio.write_image(fig, f"{save_name}.png")

一部のグラフを常に表示


先程まではプロットを表示・非表示に切り替えてスライダーの使い方を解説した。ここではy = 2xのグラフだけを常に表示する方法を解説。

と言っても難しいことはなく、各ステップでy = 2xにあたるインデックスのvisibleを常にTrueにしたらいい。

上のグラフだと初期グラフはy = 0xしか表示していないので、スライダーを動かすとそれ以降はy = 2xのグラフが常に表示されるようになる。

import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# 一部のグラフを常に表示

x = np.arange(-3, 3 + 1)
ys = {}
for num in range(10):
    y = num * x  # y = axの形
    ys[f"{num}x"] = y

# 各プロットの色
colors = (
    'red', 'blue', 'green', 'orange', 'black',
    'deeppink', 'purple', 'olive', 'deepskyblue', 'violet'
)

# 配列の要素にプロット内容を格納
plot = []
for num, (name, y) in enumerate(ys.items()):
    d = go.Scatter(
        x=x, y=y, name=name,
        marker_color=colors[num],  # プロット線の色
        showlegend=True,  # 凡例を常に表示
        visible=False  # グラフを非表示に
    )
    plot.append(d)

# 0番目(y = 0x)のグラフだけ、後からvisible=Trueにして表示する
plot[0]['visible'] = True

# スライダーの内容作成
steps = []
for num, _ in enumerate(plot):
    # 一旦全てのプロットを非表示にしてから、該当するプロットを表示に変更
    visible = [False] * len(plot)
    # 2番目(y = 2x)のグラフだけ常に表示するようにする
    visible[2] = True
    # こっちは各グラフを表示する
    visible[num] = True

    step = dict(
        label=num,  # スライダーのラベル
        method='update',  # スライダーの適用範囲はデータプロットとレイアウト
        args=[
            dict(visible=visible),  # y0のみ表示
            dict(title=f"y = {num}x"),  # グラフタイトル
        ]
    )
    steps.append(step)

# レイアウトに設置するためのスライダー作成
sliders = [
    dict(
        active=0,  # 初期状態で表示するプロットのインデックス
        # 各スライダーの傾きをスライダーの上に表示
        currentvalue=dict(prefix='傾き = '),
        steps=steps,
    )
]

# レイアウトの作成
layout = go.Layout(
    font_size=20,  # グラフ全体のフォントサイズ
    hoverlabel_font_size=20,  # ホバーのフォントサイズ
    title='y = 0x',
    yaxis_range=(-30, 30),  # 縦軸の表示範囲
    sliders=sliders  # スライダーを設置
)
# グラフの表示
fig = go.Figure(data=plot, layout=layout)
fig.show()

# # グラフ保存
prefix = 'plotly-slider'  # 保存ファイル名の接頭辞
save_name = f"{prefix}_10data_always"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html")
pio.write_image(fig, f"{save_name}.png")

複数プロットを同時に表示・非表示に


もちろん各ステップのvisibleを調節することで、複数プロットを同時に表示・非表示にすることも可能。

ここでは隣り合う2プロットずつ表示・非表示を切り替えるように設定した。この場合は0番目と1番目、2番目と3番目というようにvixibleをTrueにしたらいい。

import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

x = np.arange(-3, 3 + 1)
ys = {}
for num in range(10):
    y = num * x  # y = axの形
    ys[f"{num}x"] = y

# 配列の要素にプロット内容を格納
plot = []
colors = (
    'red', 'blue', 'green',
    'orange', 'black', 'deeppink',
    'purple', 'olive',
    'deepskyblue', 'violet'
)

for num, (name, y) in enumerate(ys.items()):
    d = go.Scatter(
        x=x, y=y, name=name,
        marker_color=colors[num],  # プロット線の色
        showlegend=True,  # 凡例を常に表示
        visible=False  # グラフを非表示に
    )
    plot.append(d)

# 0番目(y = 0x), 1番目(y = 1x)のグラフだけ、後からvisible=Trueにして表示する
plot[0]['visible'] = True
plot[1]['visible'] = True

# スライダーの内容作成
split = 2  # 2データずつ表示したい
nums = len(plot) // split  # スライダーの数は5つになる

steps = []
for num in range(nums):
    # 一旦全てのプロットを非表示にしてから、該当するプロットを表示に変更
    visible = [False] * len(plot)
    # 0番目と1番目、2番目と3番目という風に指定
    visible[split * num] = True
    visible[split * num + 1] = True

    step = dict(
        label=f"{split * num}, {split * num+1}",  # スライダーのラベル
        method='update',  # スライダーの適用範囲はデータプロットとレイアウト
        args=[
            dict(visible=visible),  # y0のみ表示
            # グラフタイトル
            dict(title=f"y = {split * num}x, {split * num + 1}x"),
        ]
    )
    steps.append(step)

# レイアウトに設置するためのスライダー作成
sliders = [
    dict(
        active=0,  # 初期状態で表示するプロットのインデックス
        # 各スライダーの傾きをスライダーの上に表示
        currentvalue=dict(prefix='傾き = '),
        steps=steps,
    )
]

# レイアウトの作成
layout = go.Layout(
    font_size=20,  # グラフ全体のフォントサイズ
    hoverlabel_font_size=20,  # ホバーのフォントサイズ
    title='y = 0x, 1x',
    yaxis_range=(-30, 30),  # 縦軸の表示範囲
    sliders=sliders  # スライダーを設置
)
# グラフの表示
fig = go.Figure(data=plot, layout=layout)
fig.show()

# グラフ保存
prefix = 'plotly-slider'  # 保存ファイル名の接頭辞
save_name = f"{prefix}_10data_multiple"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html")
pio.write_image(fig, f"{save_name}.png")

スライダーでプロットの不透明度を変更


最後に、スライダーを使ってプロットの不透明度を変更する。ここまではプロットを非表示にして該当プロット以外を隠したが、不透明度を変更することで、全プロットを表示したまま該当プロットを目立たせられる。

まずは全コードを示す。その後に色の変更を重点的に解説する。

【plotly&go.Scatter】plotlyの散布図グラフの描き方

こんな人にオススメ plotlyのと{ ...

続きを見る

なお、以下の記事で解説しているボタンに関してはredなどの色から不透明どを変更する方法を解説しているが、ここではすでにrgba形式の色から不透明度を変更する方法を解説することにする。

import copy
import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

x = np.arange(-3, 3 + 1)
ys = {}
for num in range(10):
    y = num * x  # y = axの形
    ys[f"{num}x"] = y

# 各プロットの色
# colors = (
#     'red', 'blue', 'green', 'orange', 'black',
#     'deeppink', 'purple', 'olive', 'deepskyblue', 'violet'
# )

# 色をrgbaの形式かつ不透明度を0.1にした
colors = [
    'rgba(255, 0, 0, 0.1)', 'rgba(0, 0, 255, 0.1)', 'rgba(0, 128, 0, 0.1)',
    'rgba(255, 165, 0, 0.1)', 'rgba(0, 0, 0, 0.1)', 'rgba(255, 20, 147, 0.1)',
    'rgba(128, 0, 128, 0.1)', 'rgba(128, 128, 0, 0.1)',
    'rgba(0, 191, 255, 0.1)', 'rgba(238, 130, 238, 0.1)',
]

# 配列の要素にプロット内容を格納
plot = []
for num, (name, y) in enumerate(ys.items()):
    d = go.Scatter(
        x=x, y=y, name=name,
        marker_color=colors[num],  # プロット線の色
        showlegend=True,  # 凡例を常に表示
    )
    plot.append(d)

# 0番目(y = 0x)のグラフの色を取り出す
before_color0 = plot[0]['marker.color']
print(before_color0)
# rgba(255, 0, 0, 0.1)

# 不透明度を0.1から1に変更
after_color0 = before_color0.replace('0.1)', '1)')
print(after_color0)
# rgba(255, 0, 0, 1)
plot[0]['marker.color'] = after_color0

# スライダーの内容作成
steps = []
for num, _ in enumerate(plot):
    # 不透明度を1にした、該当するプロットの色を取得
    color = colors[num].replace('0.1)', '1)')
    # colorsをコピー
    color_lst = copy.copy(colors)
    # 該当箇所だけ色を更新
    color_lst[num] = color

    step = dict(
        label=num,  # スライダーのラベル
        method='update',  # スライダーの適用範囲はデータプロットとレイアウト
        args=[
            {'marker.color': color_lst},  # プロットの色を変更
            dict(title=f"y = {num}x"),  # グラフタイトル
        ]
    )
    steps.append(step)

# レイアウトに設置するためのスライダー作成
sliders = [
    dict(
        active=0,  # 初期状態で表示するプロットのインデックス
        # 各スライダーの傾きをスライダーの上に表示
        currentvalue=dict(prefix='傾き = '),
        steps=steps,
    )
]

# レイアウトの作成
layout = go.Layout(
    font_size=20,  # グラフ全体のフォントサイズ
    hoverlabel_font_size=20,  # ホバーのフォントサイズ
    title='y = 0x',
    yaxis_range=(-30, 30),  # 縦軸の表示範囲
    sliders=sliders  # スライダーを設置
)
# グラフの表示
fig = go.Figure(data=plot, layout=layout)
fig.show()

# グラフ保存
prefix = 'plotly-slider'  # 保存ファイル名の接頭辞
save_name = f"{prefix}_10data_opacity"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html")
pio.write_image(fig, f"{save_name}.png")

色をCSSカラーからRGBaへ

# 各プロットの色
# colors = (
#     'red', 'blue', 'green', 'orange', 'black',
#     'deeppink', 'purple', 'olive', 'deepskyblue', 'violet'
# )

# 色をrgbaの形式かつ不透明度を0.1にした
colors = [
    'rgba(255, 0, 0, 0.1)', 'rgba(0, 0, 255, 0.1)', 'rgba(0, 128, 0, 0.1)',
    'rgba(255, 165, 0, 0.1)', 'rgba(0, 0, 0, 0.1)', 'rgba(255, 20, 147, 0.1)',
    'rgba(128, 0, 128, 0.1)', 'rgba(128, 128, 0, 0.1)',
    'rgba(0, 191, 255, 0.1)', 'rgba(238, 130, 238, 0.1)',
]

まずはredやblueといったCSSカラーからRGBaに変換する。RがRed、GがGreen、BがBlue、aがalpha(不透明度=opacity)に相当する。

CSSカラーの状態だと不透明度を指定できないので、RGBa形式にした。変換については色んなサイトで書かれているし、本ブログのplotlyのボタンの記事でも書いている。

注意点は文頭にrgbaをつけないといけないということ。これをつけないとエラーになったり色が反映されない事がある。

不透明度の変更

# 0番目(y = 0x)のグラフの色を取り出す
before_color0 = plot[0]['marker.color']
print(before_color0)
# rgba(255, 0, 0, 0.1)

# 不透明度を0.1から1に変更
after_color0 = before_color0.replace('0.1)', '1)')
print(after_color0)
# rgba(255, 0, 0, 1)
plot[0]['marker.color'] = after_color0

RGBa形式の色はstrで作成しているので、不透明度を1へ変更しようと思えば、ここでは文末の0.1を1に変更したらいい。

んだけど、Pythonでは以下のように文字列の変更は許可されていない。

# 文字列の変更はできない
before_color0[-4:-1] = '1'
#     before_color0[-4:-1] = '1'
# TypeError: 'str' object does not support item assignment

なので、ここでは文字列を.replaceで置き換えることにした。不透明度は最後に書かれるので、’0.1)’と指定することで、仮に色部分に0.1があっても入れ替えできる。

注意することとしては、入れ替え先を’1’ではなく’1)’とカッコ閉じるまでちゃんと書くこと。ないとエラーの原因となる。

この方法を使ってスライダー内で不透明度を変更する。

スライダー内で不透明度を変更

steps = []
for num, _ in enumerate(plot):
    # 不透明度を1にした、該当するプロットの色を取得
    color = colors[num].replace('0.1)', '1)')
    # colorsをコピー
    color_lst = copy.copy(colors)
    # 該当箇所だけ色を更新
    color_lst[num] = color

    step = dict(
        label=num,  # スライダーのラベル
        method='update',  # スライダーの適用範囲はデータプロットとレイアウト
        args=[
            {'marker.color': color_lst},  # プロットの色を変更
            dict(title=f"y = {num}x"),  # グラフタイトル
        ]
    )
    steps.append(step)

各スライダーのステップで不透明度を変更する。変数colorでさっきの不透明度変更後の色を作成。

その後にRGBaの配列である変数colorsで入れ替えを行うが、そのまま入れ替えをしてしまうと変数colorsがどんどん上書きされて、最後には全プロットで不透明度が1となってしまう。

これを防ぐために各ステップでcopyライブラリのcopy.copyでcolorsをコピーして不透明度を変更している。

また、スライダーでマーカーの色を指定する際にはdict{}で括った方法じゃないといけない。以下のように指定するとエラーとなる。

dict(marker.color=color_lst),
         ^^^^^^^^^^^^^
SyntaxError: expression cannot contain assignment, perhaps you meant "=="?

変化を見るにはもってこい

今回はplotlyのスライダーについて解説した。スライダーはある変数とかの違いを見る際にはもってこいだと思う。一方でボタンは異なる変数を見比べるときに使える。

色んな解析があるけど、その時々に応じて最適なグラフを描くことが重要。

アニメーションもあるけど、スライダーの場合は自分のタイミングでグリグリ動かしやすいし、設定も簡単。本記事でスライダーに対する理解を深めていただけると幸いだ。

関連記事

【plotly&ボタン】plotlyのupdatemenusにbuttonsを追加

こんな人にオススメ plotlyって| ...

続きを見る

【plotly&ボタン】plotlyのupdatemenusに2回押し対応のbuttonsを追加

こんな人にオススメ plotlyでボ| ...

続きを見る

【plotly&fig作成と更新】add_traceやupdate_layoutの使い方

こんな人にオススメ plotlyでグ} ...

続きを見る

【plotly&size, width】Scatterのサイズやlineの太さ一覧表を作成

こんな人にオススメ plotlyのScatterӗ ...

続きを見る

【plotly&legendまとめ】凡例の引数一覧

こんな人にオススメ plotlyのlayoutの ...

続きを見る

【plotly&fill】goで領域を塗りつぶし

こんな人にオススメ plotlyで塗| ...

続きを見る

【plotly&3D】goで3Dグラフを作成

こんな人にオススメ plotyで3Dプ ...

続きを見る

【plotly&グラフテーマ】plotly既存のthemasをグラフ化

こんな人にオススメ plotlyでグ} ...

続きを見る

スイッチボット

2022/9/11

【SwitchBotロックレビュー】これからのスタンダードになりうるスマートロック

こんな人にオススメ SwitchBotからスマートロック「SwitchBotロック」が発売された ...

生活に役立つ

2022/10/25

【メガネ厳選】クソ便利に使っているサービスやアイテム達

このページでは執筆者「メガネ」が実際に使って便利だと感じているサ ...

マウス

2022/9/11

【Logicool MX ERGO vs MX Master 3】ERGOをメインにした決定的な理由

こんな疑問・お悩みを持っている人におすすめ 執筆者はLogicoolのハイエンӠ ...

完全ワイヤレスイヤホン(TWS)

2022/11/21

【ながら聴きイヤホン比較】SONY LinkBuds、ambie、BoCoはどれがおすすめ?

こんな人におすすめ 耳を塞がない開放型のイヤホンに完全ワイヤレスӟ ...

macOSアプリケーション

2022/10/15

【M1 Mac】MacBook Proに入れている便利でニッチなアプリを21個紹介する

こんな人におすすめ MacBookを購入してLINEとか必要最低限のアプリは入れた。 ...

完全ワイヤレスイヤホン(TWS)

2022/10/23

【SENNHEISER MOMENTUM True Wireless 3レビュー】高レベルでバランス型の高音質イヤホン

こんな人におすすめ SENNHEISER MOMENTUM True Wireless 3って実際のところどうなの? 評判は良い ...

完全ワイヤレスイヤホン(TWS)

2022/11/21

【SONY WF-1000XM4レビュー】神とゴミのハーフ&ハーフ

こんな人におすすめ SONYのフラグシップモデル「SONY WF-1000XM4」ってどれくらい性 ...

完全ワイヤレスイヤホン(TWS)

2022/8/19

【Nothing ear (1)レビュー】ライトな完成度、アップデートに期待

こんな人にオススメ 完全ワイヤレスイヤホン(TWS)でスケルトンボディ ...

Pythonを学びたいけど独学できる時間なんてない人へのすゝめ

執筆者は大学の研究室・大学院にて独学でPythonを習得した。

でも社会人になったら独学で行うには時間も体力もなくて大変だ。

時間がない社会人だからこそプロの教えを乞うのが効率的。

ここでは色んなタイプに合ったプログラミングスクールの紹介をする。

  • この記事を書いた人

メガネ

ベンチャー企業のWebエンジニア駆け出し。独学のPythonで天文学系の大学院を修了→新卒を1.5年で辞める→転職→今に至る。
常時金欠のガジェット好きでM1 MacBook Pro x Galaxy S22 Ultraの狂人。
人見知りで根暗だったけど、人生楽しもうと思って良い方向に狂う→人生が楽しい

ガジェットのレビューとPythonコードを記事にしています。ぜひ楽しんでください🦊
自己紹介と半生→変わって楽しいの繰り返し

-Plotly全般
-, , ,