こんな人にオススメ
plotly
にもmatplotlib
のようにマーカー(シンボル)って存在しているの?あるならどんなものがあるのか知りたい!一覧で見せてほしい!ということで、本記事では
plotly
のプロットで使用することができるマーカー(plotly
ではsymbol
という)の形状について説明する。plotly
の公式サイトには既に一覧はあるが、個人的にまとめた部分もあるのでぜひ見ていってほしい。
python環境は以下。
- Python 3.9.2
- plotly 4.14.3
- plotly-orca 3.4.2
シンボル一覧の出力
まずはどのようなシンボルがあるのかを出力する。
全配列を出力
以下のコードでplotlyのシンボルで指定可能な文字列の一覧を出力することができる。
raw_symbols = SymbolValidator().values print(raw_symbols)ここで、
raw_symbols
にはint
型の数字とstr
型の数字と文字列があることがわかる。最初の数字2種類と次の文字列が同じシンボルを表す。イメージは以下。
-
- 円
-
0
-
'0'
-
'circle'
-
- 円
-
- 正方形
-
1
-
'1'
-
'square'
-
- 正方形
0
, '0'
, 'circle'
のどの値を使用しても同じ円のシンボルを表すことができる。
公式サイトでグラフ化
plotlyの公式サイトの「Styling Markers in Python」でシンボルについての説明や例が載っている。そしてこのページの一番最後の「Custom Marker Symbols」ではシンボル一覧がグラフ化されている。以下にサイトに載っているコードを示す。
import plotly.graph_objects as go from plotly.validators.scatter.marker import SymbolValidator raw_symbols = SymbolValidator().values namestems = [] namevariants = [] symbols = [] for i in range(0,len(raw_symbols),3): name = raw_symbols[i+2] symbols.append(raw_symbols[i]) namestems.append(name.replace("-open", "").replace("-dot", "")) namevariants.append(name[len(namestems[-1]):]) fig = go.Figure(go.Scatter(mode="markers", x=namevariants, y=namestems, marker_symbol=symbols, marker_line_color="midnightblue", marker_color="lightskyblue", marker_line_width=2, marker_size=15, hovertemplate="name: %{y}%{x}<br>number: %{marker.symbol}<extra></extra>")) fig.update_layout(title="Mouse over symbols for name & number!", xaxis_range=[-1,4], yaxis_range=[len(set(namestems)),-1], margin=dict(b=0,r=0), xaxis_side="top", height=1400, width=400) fig.show()
このブログでは使用しない、箱にどんどん入れていくスタイルの書き方。執筆者流に書き換えたのが以下。
import sys import plotly import plotly.io as pio import plotly.graph_objects as go from plotly.validators.scatter.marker import SymbolValidator # このファイルの2つ上の階層にplotlyのlayoutテンプレートがある sys.path.append('../../') from plotly_layout_template import * import plotly_layout_template as template # グラフ保存のpath指定 pio.orca.config.executable = ('/Applications/orca.app/Contents/MacOS/orca') # plotlyのシンボル一覧 raw_symbols = SymbolValidator().values def official_graph(): """plotlyの公式サイトに記載されているmarkerのシンボル一覧をグラフ化 """ # 各シンボルの大枠の名称 namestems = [] # 各シンボルの付加要素(塗りつぶしか塗らないか塗りつぶしドットか塗りつぶさないドットか) namevariants = [] # シンボルを表す数字 symbols = [] for i in range(0, len(raw_symbols), 3): name = raw_symbols[i + 2] symbols.append(raw_symbols[i]) # circleとcircle-openは大枠ではcircleなので-openを削除。dotも同様 namestems.append(name.replace("-open", "").replace("-dot", "")) # シンボルの名称から大枠の部分の文字列を削除して付加要素のみを抽出 namevariants.append(name[len(namestems[-1]):]) plot = [] d = go.Scatter( mode="markers", x=namevariants, y=namestems, marker=dict( symbol=symbols, color="lightskyblue", size=15, line=dict(color="midnightblue", width=2), ), hovertemplate="name: %{y}%{x}<br>number:" + "%{marker.symbol}<extra></extra>" ) plot.append(d) layout = go.Layout( height=1400, width=400, title=dict( text="Mouse over symbols for name & number!", ), xaxis=dict( range=[-1, 4], ), xaxis_side="top", yaxis=dict( range=[len(set(namestems)), -1], ), margin=dict(b=0, r=0), ) fig = go.Figure(data=plot, layout=layout) plotly.offline.iplot(fig) # 作成したグラフを保存 pio.write_html( fig, "plotly-symbol_plotly_official.html", auto_open=False ) # このままグラフを保存するとなぜか横長のグラフになってしまう # pio.write_image(fig, "plotly-symbol_plotly_official.png") official_graph()
なぜかこのコードで画像を保存するとpngファイルが横長になる。どうすれば解決できそうか大体は見当がついているが、とりあえずは先に書くことを優先する。これでできるグラフが以下。
plotly公式サイトでのマーカーシンボル一覧
横軸が無名のシンボルが塗りつぶしに該当し、-open
が塗りつぶさない、-dot
が塗りつぶして中心に点を打った、-open-dot
が塗りつぶさない中心に点を打ったシンボルに該当する。なお、バッテンを表すx-thin
などには塗りつぶす場所がないので-open
や-dot
の機能は付与されていない。
自己流のグラフ化
上述の公式サイトでのグラフがとても見やすいのでこれでも十分だが、あまりにも縦長すぎると感じた。ここでは横長にしつつ一覧性を保つコードを書いたので紹介する。 続きを見るplotly
のレイアウトテンプレートについては以下参照。
【plotlyテンプレート】plotlyのグラフ作成テンプレート
def graph(columns: int): """plotlyのマーカー一覧をグラフ化 Parameters ---------- columns : int グラフの列数指定 """ # intだけ抽出 int_symbol = [x for x in raw_symbols if type(x) is int] # 文字列だけ抽出 str_symbol = [x for x in raw_symbols if not str(x).isdecimal()] plot = [] for num, symbols in enumerate(str_symbol): d = go.Scatter( mode="markers", # xは切り捨て、yは約数でで場所をずらしている x=[num // columns], y=[num % columns], name=symbols, marker=dict( symbol=symbols, color="lightskyblue", size=15, line=dict(color="midnightblue", width=2), ), hoverlabel=dict( font=dict( family='Times New Roman', size=15 ) ), hovertemplate=f"{symbols}<br>{int_symbol[num]}", + "<extra></extra>", # プロットをグループ化 legendgroup=num // columns, ) plot.append(d) layout = go.Layout( template=template.plotly_layout(), title=dict( text="Mouse over symbols for name & number!", ), xaxis=dict( range=[-1, len(str_symbol) / columns], ), xaxis_side="top", yaxis=dict( range=[columns, -1], ), # 凡例のグループを横に並べる legend=dict(orientation='h'), ) fig = go.Figure(data=plot, layout=layout) plotly.offline.iplot(fig) # 作成したグラフを保存 pio.write_html( fig, "plotly-symbol_plotly.html", auto_open=False ) pio.write_image(fig, "plotly-symbol_plotly.png") graph( columns=16 )
このコードではcolumns
を指定することで表示列数を変更することができる。今は16にしているので16列のグラフとなる。
また、int_symbol
でシンボルの中で数字のものだけ、str_symbol
でシンボルの中でシンボル名のものだけを引っ張ってきた。グラフのx
, y
はそれぞれraw_symbols
の各要素の番号(何番目の要素か)を
x
: 16で割った時の商 = 要素の値が16の倍数になるまでは同じ値y
: 16で割った時の余り = 0から15の間
というふうに設定することで綺麗に並ぶように設定している。完成したグラフは以下。
自作したplotlyのマーカーのシンボル一覧
ここで、新規キャラとしてlegendgroup
という変数が出てくる。この変数はプロットをグループ化するというもので、凡例を表示・非表示する時にグループで同時に行うというもの。これを使用することで凡例をまとめることができる反面、個々で凡例を表示・非表示にすることが出来なくなる。
では、なぜこの変数を使用したのかというとplotly
の凡例は列数を変更することができないから。legendgroup
を使用することでグループごとにまとめられて中途半端に改行された凡例ではなくなる。今回は各グループが1列に対応する。
HTML表示
上記のグラフをHTML表示したものが以下。今回は情報量が多いので、グラフをレスポンシブ対応にしたら凝縮されてしまった。凡例は途切れる部分がスクロールできるように変更されている。ありがてぇ。
工夫次第でオリジナルなシンボルができる
plotly
のシンボルは塗りつぶし有無やドット有無がある。これを自分で塗りつぶしだけ使用したり、塗りつぶしと塗りつぶしなしとを使用したりとすれば自由自在にグラフを作ることができる。是非とも色々といじってほしい。