こんな人にオススメ
plotly
でグラフを描く時にadd_trace
とかupdate_layout
とかあるけど、これらは一体なんなの?
ということで、今回はpythonのplotly
でグラフを描くときに出てくるadd_trace
やupdate_layout
などについて解説する。
実はplotlyでグラフを描く際には色んな方法があって、初めはどの方法がどんなどんなプロットになるのかがわかりにくい。実際、執筆者もplotly
を使い始めた時はよくわからなかった。
今回はグラフ描画時のこれらのコードで何ができるのか、どのような挙動になるのかを解説するので、plotly
学習のきっかけにしていただけると幸いだ。
なお、今回の記事はplotly
公式の「Creating and Updating Figures in Python」の内容をベースに作成している。
python環境は以下。
- Python 3.10.1
- plotly 5.4.0
- plotly-orca 3.4.2
作成したコード全文
下準備(import
)
import plotly.graph_objects as go import plotly.io as pio
まずは下準備としてのimport
関連。今回はplotly
のgo
を使って解説する。plolty
ではgo
以外にもpx
なるライブラリもあり、こちらはよりサクッとグラフを描くことが可能。
ただ、plotlyの
グラフ描画のコード内容を知るならgo
を使ったほうが細かいのでおすすめ。[px
についての記事](https://megatenpa.com/category/python/plotly/px/)は以下。
-
-
【plolty&棒グラフ】px.barでバーチャートを作成
2022/8/19
こんな人にオススメ plotlyのpxで棒グラ ...
-
-
【plotly&ガントチャート】px.timelineでGantt Chartsを作成
2022/8/19
こんな人にオススメ plotlyでガントチ& ...
-
-
【plotly&fill】px.areaで積み上げ塗りつぶし
2023/1/14
こんな人にオススメ pxで塗りつぶ{ ...
-
-
【plotly&px.scatter】pxでの散布図の描き方
2022/8/19
こんな人にオススメ plotlyの中にpxって ...
go.Figure
の引数data
にlist
でプロットデータを格納
まずはこのブログ「M天パ」で使っている方法。予めプロットするデータをlist
などで作成しておき、最後にfig
に入れる。
執筆者がplotly
を使い始めた際に一番理解しやすかった方法だ。この方法だとプロットとフィギュアを別々で管理することができる。
今回は上の図のように2種類のプロットを用意し、それぞれを引数plot
に格納、最後にfig
の引数data
に入れる。行数や手間は多いけど、1ステップがわかりやすいと思う。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) # 全プロットを入れるためのlist plot = [] # プロットをlistへ格納 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット plot.append(d1) # プロットを格納 d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット plot.append(d2) # プロットを格納 fig = go.Figure(data=plot) # Figureの作成 fig.show() # Figureの表示 # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_append_plot" 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")
go.Figure
の引数data
に直接プロットデータを格納
続いてはgo.Figure
の中に直接プロットデータを入れるという方法。さっきは一旦、変数plot
に入れたけど、今回は直接入れる。
ここでのプロットのようにシンプルなグラフを描きたいときはこれでもいいだろう。ただし、go.Scatter
の引数が多いグラフを描こうした時は、go.Figure
内がゴチャゴチャしてしまうので注意が必要。
グラフの作成のためのコードはさっきと同じなので、できるグラフのさっきと同じ。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) # Figureに直接入れる fig = go.Figure( data=[ go.Scatter(x=x, y=y1, name='y1'), go.Scatter(x=x, y=y2, name='y2') ] ) fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_append_plot_direct" pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca' pio.write_html(fig, f"{save_name}.html", config=None,) pio.write_image(fig, f"{save_name}.png")
add_trace
で1プロットずつ格納
今度はちょっとテイストが異なり、一旦go.Figure
でfig
を作成、そこにfig.add_trace
でどんどんプロットを追加する方法。ネットでplotly
のプロット方法を調べると、この方法で書かれた記事が多くヒットする。
ここではy1
, y2
のプロットを変数d1
, d2
においてからfig.add_trace
に入れているけど、直接fig.add_trace
の中にプロットデータを入れてもいい。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット fig.add_trace(d1) # figにd1を追加 d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット fig.add_trace(d2) # figにd2を追加 fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_add_trace" 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")
なお、fig.add_
から始まるコードは他にもある。一部は後で解説するが以下だけ種類がある。多すぎる。
# fig.add_一覧 fig.add_annotation fig.add_bar fig.add_barpolar fig.add_box fig.add_candlestick fig.add_carpet fig.add_choropleth fig.add_choroplethmapbox fig.add_class fig.add_cone fig.add_contour fig.add_contourcarpet fig.add_densitymapbox fig.add_funnel fig.add_funnelarea fig.add_heatmap fig.add_heatmapgl fig.add_histogram fig.add_histogram2d fig.add_histogram2dcontour fig.add_hline fig.add_hrect fig.add_icicle fig.add_image fig.add_indicator fig.add_isosurface fig.add_layout_image fig.add_mesh3d fig.add_ohlc fig.add_parcats fig.add_parcoords fig.add_pie fig.add_pointcloud fig.add_sankey fig.add_scatter fig.add_scatter3d fig.add_scattercarpet fig.add_scattergeo fig.add_scattergl fig.add_scattermapbox fig.add_scatterpolar fig.add_scatterpolargl fig.add_scattersmith fig.add_scatterternary fig.add_shape fig.add_splom fig.add_streamtube fig.add_sunburst fig.add_surface fig.add_table fig.add_trace fig.add_traces fig.add_traits fig.add_treemap fig.add_violin fig.add_vline fig.add_volume fig.add_vrect fig.add_waterfall
add_trace
は1プロットの追加のみ
# add_traceで複数プロットを入れようとするとエラー fig.add_trace([d1, d2]) # ValueError: # Invalid element(s) received for the 'data' property of # Invalid elements include: [[Scatter({ # 'name': 'y1', 'x': [1, 2, 3], 'y': [1, 3, 2] # }), Scatter({ # 'name': 'y2', 'x': [1, 2, 3], 'y': [4, 2, 3.5] # })]] # The 'data' property is a tuple of trace instances # that may be specified as: # - A list or tuple of trace instances # (e.g. [Scatter(...), Bar(...)]) # - A single trace instance # (e.g. Scatter(...), Bar(...), etc.) # - A list or tuple of dicts of string/value properties where: # - The 'type' property specifies the trace type # One of: ['bar', 'barpolar', 'box', 'candlestick', # 'carpet', 'choropleth', 'choroplethmapbox', # 'cone', 'contour', 'contourcarpet', # 'densitymapbox', 'funnel', 'funnelarea', # 'heatmap', 'heatmapgl', 'histogram', # 'histogram2d', 'histogram2dcontour', 'icicle', # 'image', 'indicator', 'isosurface', 'mesh3d', # 'ohlc', 'parcats', 'parcoords', 'pie', # 'pointcloud', 'sankey', 'scatter', # 'scatter3d', 'scattercarpet', 'scattergeo', # 'scattergl', 'scattermapbox', 'scatterpolar', # 'scatterpolargl', 'scattersmith', # 'scatterternary', 'splom', 'streamtube', # 'sunburst', 'surface', 'table', 'treemap', # 'violin', 'volume', 'waterfall'] # - All remaining properties are passed to the constructor of # the specified trace type # (e.g. [{'type': 'scatter', ...}, {'type': 'bar, ...}])
fig.add_trace
は1プロットの追加にのみ対応している。したがって、上のコードのように複数プロットを入れるとエラーとなる。
複数プロットを同時に追加したいときは次に解説するadd_traces
を使用する。こっちはtraces
と複数形になっている。
add_traces
で複数プロットを一気に格納
fig.add_traces
と、trace
を複数形のtraces
にすることで複数プロットを同時に追加可能。この際、プロットはtuple
やlist
などで一括りにしないとエラーとなる。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット fig.add_traces((d1, d2)) # 複数形にすると複数プロットを追記可能 fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_add_traces" 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")
add_scatter
, add_bar
などで直接格納
先程のfig.add_
一覧に載っているプロットの種類であれば、直接プロットの種類を選択して追加可能。いちいちfig.add_trace
の中でプロットの種類を選択しなくてもよくなる。
ここではfig.add_scatter
で散布図を、fig.add_bar
で棒グラフを作成した。fig.add_
一覧を再度載せるので、各シチュエーションで使いたいものをピックアップしていただきたい。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 fig.add_scatter(x=x, y=y1, name='y1') # scatterを直接追加 fig.add_bar(x=x, y=y2, name='y2') # barを直接追加 fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_add_scatter_bar" 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")
# fig.add_一覧 fig.add_annotation fig.add_bar fig.add_barpolar fig.add_box fig.add_candlestick fig.add_carpet fig.add_choropleth fig.add_choroplethmapbox fig.add_class fig.add_cone fig.add_contour fig.add_contourcarpet fig.add_densitymapbox fig.add_funnel fig.add_funnelarea fig.add_heatmap fig.add_heatmapgl fig.add_histogram fig.add_histogram2d fig.add_histogram2dcontour fig.add_hline fig.add_hrect fig.add_icicle fig.add_image fig.add_indicator fig.add_isosurface fig.add_layout_image fig.add_mesh3d fig.add_ohlc fig.add_parcats fig.add_parcoords fig.add_pie fig.add_pointcloud fig.add_sankey fig.add_scatter fig.add_scatter3d fig.add_scattercarpet fig.add_scattergeo fig.add_scattergl fig.add_scattermapbox fig.add_scatterpolar fig.add_scatterpolargl fig.add_scattersmith fig.add_scatterternary fig.add_shape fig.add_splom fig.add_streamtube fig.add_sunburst fig.add_surface fig.add_table fig.add_trace fig.add_traces fig.add_traits fig.add_treemap fig.add_violin fig.add_vline fig.add_volume fig.add_vrect fig.add_waterfall
update_traces
で既存データを更新
続いてはupdate_traces
。update
と名がついているからわかりやすいが、これは既存のプロットデータ(traces
)を更新する。
新規で入れても意味がない
まずは先ほどと同じように空のfigに対して適用してみる。しかし、元から何もプロットデータがない状態なので、グラフをはまっさらのまま。
fig
をプリントしてもデータ部分には何も入っていないので当たり前。なお、layout
のtemplate
はグラフのテーマに相当する。以下で解説している。
-
-
【plotly&グラフテーマ】plotly既存のthemasをグラフ化
続きを見る
import plotly.graph_objects as go import plotly.io as pio # update_tracesをプロットの格納に使っても何も表示されない x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット fig.update_traces(d1) d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット fig.update_traces(d2) print(fig) # Figure({ # 'data': [], 'layout': {'template': '...'} # }) fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_update_tarces_miss" 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")
既存データのアップデートに使用可能
update_traces
は既存のプロットに対して適用されるので、予めfig
にプロットを入れておく必要がある。ここでは先ほどと同じようにy1
, y2
でグラフを作成、その後にupdate_traces
でプロットを線から点に変更した。
fig.update_traces
の引数mode
はgo.Scattrer
の引数で、プロットの種類を選択できる。ここではmode=’marker’
でプロットの種類を点だけにしている。デフォルトは既に見てきたように’lines+markers’
。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット fig.add_traces((d1, d2)) fig.update_traces(mode='markers') # プロットのモードをマーカーだけに更新 fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_update_traces" 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")
なお、fig.update_
で始まるものは以下。基本的にはプロット関連が多い。
# fig.updateシリーズ fig.update_annotations fig.update_coloraxes fig.update_geos fig.update_layout fig.update_layout_images fig.update_mapboxes fig.update_polars fig.update_scenes fig.update_shapes fig.update_smiths fig.update_ternaries fig.update_traces fig.update_xaxes fig.update_yaxes
全プロットに共通した引数じゃないとエラー
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット d2 = go.Bar(x=x, y=y2, name='y2') # y2のプロット fig.add_traces((d1, d2)) # go.Barの棒グラフには引数modeはないからエラー fig.update_traces(mode='markers') # プロットのモードをマーカーだけに更新 # ValueError: Invalid property specified for object of type plotly.graph_objs.Bar: 'mode' # Did you mean "base"?
先程の例だとy1
, y2
どちらもgo.Scatter
で引数mode
を編集した。しかし、引数mode
がないgo.Bar
を使用したときはエラーとなる。
上の例だとy2
のプロットがgo.Bar
なので、fig.update_traces
でmode
を指定するとエラーとなる。
この状況でy1
のmode
を変更したいなら次で解説する引数selector
を使用しなければいけない。
selector
で更新対象を選択
一部のプロットの引数のみを変更したい場合はupdate_traces
で引数selector
を使用すれば良い。
ここではname=’y1’で
プロット名がy1のものを選んでいるが、プロットのtype=’scatter’
のようにプロットのタイプで指定することも可能。また、marker_color
やmode
でも指定可能なので、状況に応じて適切な選択が可能。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット d2 = go.Bar(x=x, y=y2, name='y2') # y2のプロット fig.add_traces((d1, d2)) fig.update_traces( mode='markers', marker_symbol='star', # マーカーの形状を四角形に marker_size=30, # マーカーのサイズを30に selector=dict(name='y1') # selectorでどのプロットに対して更新するか選択可能 ) fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_update_traces_selector" 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")
overwrite
で引数を上書き
また、update_traces
の引数overwrite=True
で設定内容を上書きすることが可能。ここでは予めmarker_color=’red’
でマーカーの色を赤色にしたfigを
上書きで不透明度opacity=0.2
に変更した。
こうすることで、元々の赤色の設定が上書きによって消え、不透明度だけが反映されることになる。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure(go.Bar(x=x, y=y1, name='y1', marker_color='red')) print(fig) # Figure({ # 'data': [{'marker': {'color': 'red'}, 'name': 'y1', 'type': 'bar', 'x': [1, 2, 3], 'y': [1, 3, 2]}], # 'layout': {'template': '...'} # }) # 透明度で上書き fig.update_traces( overwrite=True, # 上書きする marker={'opacity': 0.2} # 透明度を変更 ) print(fig) # Figure({ # 'data': [{'marker': {'opacity': 0.2}, 'name': 'y1', 'type': 'bar', 'x': [1, 2, 3], 'y': [1, 3, 2]}], # 'layout': {'template': '...'} # }) fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_update_traces_overwrite" 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")
アンダースコア_
だと追加になる
ただし、overwrite
する内容をアンダースコア_
で繋いでしまうと、上書きではなく追加になることに注意。公式ではこのアンダースコアについて以下の記述がある。
In the example below, the red color of markers is overwritten when updating
marker
inupdate_traces()
withoverwrite=True
. Note that setting insteadmarker_opacity
with the magic underscore would not overwritemarker_color
because properties would be overwritten starting only at the level ofmarker.opacity
.
要するに、ここの例だとmarker_opacity
で書くとopacity
の内容だけが更新され、marker
全体には影響がないということ。一方で、marker={'opacity': 0.2}
とするとmarker
自体をこのように書き換えるので上書きになる。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure(go.Bar(x=x, y=y1, name='y1', marker_color='red')) print(fig) # Figure({ # 'data': [{'marker': {'color': 'red'}, 'name': 'y1', 'type': 'bar', 'x': [1, 2, 3], 'y': [1, 3, 2]}], # 'layout': {'template': '...'} # }) # アンダースコアを使った省略方法だと上書きじゃなくて追記になる fig.update_traces( overwrite=True, # 上書きする marker_opacity=0.2 # アンダースコアの書き方にすると上書きされない ) print(fig) # Figure({ # 'data': [{'marker': {'color': 'red', 'opacity': 0.2}, 'name': 'y1', 'type': 'bar', 'x': [1, 2, 3], 'y': [1, 3, 2]}], # 'layout': {'template': '...'} # }) fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_update_traces_overwrite_underscore" 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")
for_each_trace
でfig
を後から追記・修正
ちょっと応用的な内容だけど、一度作成したfig
を後から修正する際にはfig.for_each_trace
を使用することができる。
これを使うことで、for
を使って数行かけて変更しなければいけない内容を1行でサクッと変更することができる。
lambda
文で所定の動作を1行で
fig.for_each_trace
はlambda
式とともに使われることが多い、fig
内の特定の引数を全て書き換えてくれるというもの。for
で全プロットについて書き換えるところを1行で済ませるイメージ。
ここではmarker_symbol=’square’
でマーカーシンボルを全て四角形に変更した。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット fig.add_traces((d1, d2)) # 複数形にすると複数プロットを追記可能 print(fig) # Figure({ # 'data': [{'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...'} # }) # マーカーのシンボルをsquareに変更 fig.for_each_trace(lambda t: t.update(marker_symbol='square')) print(fig) # Figure({ # 'data': [{'marker': {'symbol': 'square'}, 'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'marker': {'symbol': 'square'}, 'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...'} # }) fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_for_each_trace" 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")
for
文でも追記・修正可能
lambda
式とか面倒なものが出てきたけど、結局のところは以下とやっていることは同じ。fig
の中のdata
部分について、全プロットのマーカーシンボルを変更している。
以下ではlambda
式を使って全プロットを対象にしていた内容を、for
で書いている。パッと見のわかりやすさだと
forを使った方がいいかもしれない。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット fig.add_traces((d1, d2)) # 複数形にすると複数プロットを追記可能 # forを使って1プロットずつ中身を見て、マーカーシンボルを変更することも可能 for num, _ in enumerate(fig['data']): fig['data'][num]['marker_symbol'] = 'square' print(fig) # Figure({ # 'data': [{'marker': {'symbol': 'square'}, 'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'marker': {'symbol': 'square'}, 'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...'} # }) fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_for_each_trace_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")
if
を使って条件分岐
さっきまでは全プロットに対して、マーカーを四角形に変更したが、if
を使うことで特定のプロットに対してのみの適用も可能。以下ではy1
だけシンボルを四角形にした。
なお、if
で当てはまらない条件についてはelse
で処理されるが、特に処理内容がない場合は()
を記述する必要がある。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット fig.add_traces((d1, d2)) # 複数形にすると複数プロットを追記可能 print(fig) # Figure({ # 'data': [{'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...'} # }) # y1だけシンボルを変更 fig.for_each_trace(lambda trace: trace.update(marker_symbol='square') if trace.name == 'y1' else ()) print(fig) # Figure({ # 'data': [{'marker': {'symbol': 'square'}, 'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'marker': {'symbol': 'square'}, 'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...'} # }) # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_for_each_traces_if" 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")
if
を使うならelse
は必須
import plotly.graph_objects as go import plotly.io as pio fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット fig.add_traces((d1, d2)) # 複数形にすると複数プロットを追記可能 # elseで行う内容がなくてもelseは書かないといけない fig.for_each_trace(lambda trace: trace.update(marker_symbol='square') if trace.name == 'y1') # fig.for_each_trace(lambda trace: trace.update(marker_symbol='square') if trace.name == 'y1') # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # SyntaxError: expected 'else' after 'if' expression
else
以下で何も処理することがないからelse
を省略しようとするとエラー。必ずelse
とセットにする必要がある。
go.Figure
の引数layout
にlist
でレイアウトを格納
ここまでプロットについて書いてきたが、レイアウトについても同様に色んな書き方がある。まずは執筆者がよく使う、一旦他の変数にレイアウト情報を入れるスタイル。
イメージはプロットの時と同じで、何かしらの変数(ここではlayout
)で内容を設定してから、go.Figure
の引数layout
に入れる。
ここでは横軸・縦軸の軸ラベルを設定してみた。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) # 全プロットを入れるためのlist plot = [] # プロットをlistへ格納 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット plot.append(d1) # プロットを格納 d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット plot.append(d2) # プロットを格納 # レイアウトの作成 layout = go.Layout(xaxis_title='x', yaxis_title='Y') # dataとともにlayoutも入れられる fig = go.Figure(data=plot, layout=layout) # Figureの作成 print(fig) # Figure({ # 'data': [{'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...', 'xaxis': {'title': {'text': 'x'}}, 'yaxis': {'title': {'text': 'Y'}}} # }) fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_append_layout" 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")
update_layout
でレイアウトの更新
レイアウトの場合もupdate
が可能。レイアウトはadd_layout
のように追加するスタイルではなく更新するスタイル。なお、annotation
など一部引数についてはadd
で追加可能。
update_layout
もその中で軸ラベルの編集を行なった。やっていることは同じ。書き方が異なるだけだ。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット fig.add_traces((d1, d2)) # 複数形にすると複数プロットを追記可能 print(fig) # Figure({ # 'data': [{'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...'} # }) # 既存のfigに軸ラベルを追加 fig.update_layout(xaxis_title='x', yaxis_title='Y') print(fig) # Figure({ # 'data': [{'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...', 'xaxis': {'title': {'text': 'x'}}, 'yaxis': {'title': {'text': 'Y'}}} # }) fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_update_layout" 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")
update_xaxes
, update_yaxes
で直接変更可能
なお、横軸xaxes
、縦軸yaxes
についてはそれぞれupdate_xaxes
, update_yaxes
で直接変更可能。fig.upddate_
一覧は以下だった。
直接変更することができるから、引数は軸ラベルのテキストを決めるtitle
だけでよくなる。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット fig.add_traces((d1, d2)) # 複数形にすると複数プロットを追記可能 print(fig) # Figure({ # 'data': [{'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...'} # }) # figに直接追加も可能 fig.update_xaxes(title='x') fig.update_yaxes(title='y') print(fig) # Figure({ # 'data': [{'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...', 'xaxis': {'title': {'text': 'x'}}, 'yaxis': {'title': {'text': 'y'}}} # }) fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_update_xyaxes" 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")
ピリオド.
を使ってプロパティへアクセス
最後にピリオド.を使った変更方法を解説する。fig
はdict
のように扱うことができるので、以下のようにピリオドを使用することで深い階層にアクセスすることが可能。
1行目がピリオド使用の方法、2行目がカッコを使ってアクセスする方法。個人的にはカッコを使う方がエディタ上での色が変わるからわかりやすい。ただ、ピリオドの方が短く書くことができる。
fig.layout.title.text = 'text' fig['layout']['title']['text'] = 'text'
layout
に対してピリオドでアクセス
まずはレイアウトから。fig
の中にはdata
とlayout
があるので(他にもアニメーションで使用するframes
がある)、その中のlayout
を.でアクセス。
さらに.でlayout
の中のtitle
と、title
の中のtext
にもアクセス。最後に= ‘text’
とすることで、グラフタイトルを’text’
に変更することが可能になる。
ここではグラフタイトルにしたけど、もちろん他の引数にも適用可能。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット fig.add_traces((d1, d2)) # 複数形にすると複数プロットを追記可能 print(fig) # Figure({ # 'data': [{'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...'} # }) fig.layout.title.text = 'text' # # 意味としては以下と同じ # fig['layout']['title']['text'] = 'text' print(fig) # Figure({ # 'data': [{'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...', 'title': {'text': 'text'}} # }) fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_change_layout_period" 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")
trace
に対してピリオドでアクセス
trace
の場合はちょっと面倒。というのも、レイアウトのように1つのグラフに1つの対応ではなく、1つのグラフに対して複数のプロットが想定されるから。
したがって、fig.data
でdata
にアクセスした後にどのプロットを選択するのかを選ばないといけない。これについてはピリオドで対応できないので[0]
のようにインデックス指定する必要がある。
ここでは0番目、すなわちy1
のマーカーのシンボルをsquare
に変更した。
import plotly.graph_objects as go import plotly.io as pio x = (1, 2, 3) y1 = (1, 3, 2) y2 = (4, 2, 3.5) fig = go.Figure() # 先のFigureを作成 d1 = go.Scatter(x=x, y=y1, name='y1') # y1のプロット d2 = go.Scatter(x=x, y=y2, name='y2') # y2のプロット fig.add_traces((d1, d2)) # 複数形にすると複数プロットを追記可能 print(fig) # Figure({ # 'data': [{'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...'} # }) print(fig.data) # figの中のdata一覧 # (Scatter({ # 'name': 'y1', 'x': [1, 2, 3], 'y': [1, 3, 2] # }), Scatter({ # 'name': 'y2', 'x': [1, 2, 3], 'y': [4, 2, 3.5] # })) print(fig.data[0]) # dataの0番目=y1 # Scatter({ # 'name': 'y1', 'x': [1, 2, 3], 'y': [1, 3, 2] # }) print(fig.data[0].marker) # y1のマーカー # scatter.Marker() print(fig.data[0].marker.symbol) # y1のマーカーのシンボル # None fig.data[0].marker.symbol = 'square' # シンボルをsquareに変更 print(fig.data[0].marker.symbol) # square print(fig) # Figure({ # 'data': [{'marker': {'symbol': 'square'}, 'name': 'y1', 'type': 'scatter', 'x': [1, 2, 3], 'y': [1, 3, 2]}, # {'name': 'y2', 'type': 'scatter', 'x': [1, 2, 3], 'y': [4, 2, 3.5]}], # 'layout': {'template': '...'} # }) fig.show() # グラフ保存 prefix = 'plotly-creating-updating-figures' # 保存ファイル名の接頭辞 save_name = f"{prefix}_change_plot_period" 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
でプロットを作成する方法について色々と紹介した。今回の内容を全て書けるようになるのが一番だけど、まずは自分に合ったものから取り入れ、そこから派生させる方がハードルが低いからおすすめ。
本記事をきっかけにplotly
で色んな使いやすいグラフを描けるようになっていただけると幸いだ。
関連記事
-
-
【plotly&legendまとめ】凡例の引数一覧
続きを見る
-
-
【plotly&pattern】棒グラフとかのパターンまとめ
続きを見る
-
-
【plotly&ボタン】plotlyのupdatemenusにbuttonsを追加
続きを見る
-
-
【plotly&棒グラフ】go.Barでバーチャートを作成
続きを見る
-
-
【plotly&fill】goで領域を塗りつぶし
続きを見る
-
-
【plotly&スライダー】plotlyのslidersにスライダーを追加
続きを見る
-
-
【plotly&3D】goで3Dグラフを作成
続きを見る
-
-
【plotly&size, width】Scatterのサイズやlineの太さ一覧表を作成
続きを見る