こんな人にオススメ
plotly
ではグラフにスライダーをつけることができるらしいけど、どうやって追加するの?
ということで、今回はplotly
にスライダー機能を追加する方法を解説する。この機能を使用することで、変数などの流れが見やすくなる。
plotly
ではボタンの機能が有名だけど、スライダーはボタンをスライド方式にしただけ。ほぼほぼ書き方はボタンと同じ。ボタン自体とボタンとスライダーの比較記事は以下。
-
-
【plotly&ボタン】plotlyのupdatemenusにbuttonsを追加
続きを見る
-
-
【plotly&ボタンとスライダー】goとpxでのupdatemenusとsliders
続きを見る
なお、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
なお、新しく立ち上げたサイト「Pro天パ」ではリライト(書き直し)した記事を公開している。併せてご覧いただきたい。
作成したコード全文
下準備(import
)
import copy import numpy as np import plotly.graph_objects as go import plotly.io as pio
まずは下準備としてのimport
関連。今回はplotly
のgo
の散布図go.Scatter
を使用して解説する。copy
とnumpy
についてはデータの作成などに使用する。pio
はplotly
のグラフ保存に使用する。
go.Scatter
とpio
については以下参照。
-
-
【plotly&go.Scatter】plotlyの散布図グラフの描き方
続きを見る
-
-
【plotly&orca】plotlyで静止画保存(orca)
続きを見る
スライダーなしのグラフ
まずはスライダーなしのグラフから。今回は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
がレイアウト関連
- 1つ目の
今回は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=0
でy0
のボタンが押されるようにするとおかしなことになる。上のグラフがそう。
なお、ボタンの場合は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データのグラフで少し応用
ということで、これでスライダーの基礎は終わったんだが、少しデータ量の多いグラフで応用を効かせてみる。
ここではdict
のys
で縦軸の配列を作成、各プロットの色も変数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の散布図グラフの描き方
続きを見る
なお、以下の記事で解説しているボタンに関しては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のupdatemenusに2回押し対応のbuttonsを追加
続きを見る
-
-
【plotly&fig作成と更新】add_traceやupdate_layoutの使い方
続きを見る
-
-
【plotly&size, width】Scatterのサイズやlineの太さ一覧表を作成
続きを見る
-
-
【plotly&legendまとめ】凡例の引数一覧
続きを見る
-
-
【plotly&fill】goで領域を塗りつぶし
続きを見る
-
-
【plotly&3D】goで3Dグラフを作成
続きを見る
-
-
【plotly&グラフテーマ】plotly既存のthemasをグラフ化
続きを見る