こんな人にオススメ
plotly
でグラフを描いているんだけど、設定する項目が多すぎてコードが長くなりがち。
どうにか楽してコードを短くしたい。
ということで、今回は執筆者が最近実践しているplotly
のコード短縮について解説する。既に知っている人や実践している人にとっては今更かよ感はあるけど、今更なんよ。
もっと早く気づけば、1つのグラフに300行も使わなくても良かったと今では思う。困ったものだ。
で、どうやってコードを短くするかというと、同じ処理は関数化してしまうということ。要するに雛形・テンプレートを予め作成して、これにその時々のデータを設定するということ。
どんな感じかは本記事で明らかになる。python環境は以下。
- Python 3.9.4
- numpy 1.20.3
- matplotlib 3.4.2
- plotly 4.14.3
- plotly-orca 3.4.2
下準備
import sys import numpy as np import matplotlib import matplotlib.cm as cm import plotly import plotly.graph_objects as go import plotly.io as pio sys.path.append('../../') import plotly_layout_template as template x = np.arange(0, 10, 0.2)
まずは今回解説するコードの下準備のimport
関連。いつも通りのメンツ。plotly_layout_template
は執筆者が作成したplotly
のテンプレート。詳しくは以下。
-
-
【plotlyテンプレート】plotlyのグラフ作成テンプレート
続きを見る
コードを下に続けてグラフ化
今回はdict
にデータを複数個、格納してグラフを作成する。今は要素数は3つだけだが執筆者の研究では最低でも9つで、このようなdictが数十個も存在していた。
データは線形と三角関数
y = { 'y = x': x, 'y = sin(x)': np.sin(x), 'y = cos(x)': np.cos(x), }
まずは上のdict
にある直線とsin関数、cos関数をplotly
を使ってグラフ化してみる。
グラフの表示と保存は引数で管理
graph_y( pic=True, save=True, )
ここで1つの工夫としてグラフの表示と保存は引数で行う。どういうことかというと、作成したグラフを実際にブラウザ上で表示するか否かと、作成したグラフをファイルとして保存するか否かをdef
の関数の引数で決めるということ。
こうすることで、関数を使用するときに引数部分の内容を変更するだけでグラフの挙動を変更することができる。イメージは上のコード。これを含めた全体コードを書くと以下のようになる。
def graph_y(pic=False, save=False): """dictデータを各keyごとにプロット Parameters ---------- pic : bool, optional 作成したグラフを表示するか否か, by default False save : bool, optional 作成したグラフを保存するか否か, by default False """ plot = [] for num, (name, val) in enumerate(y.items()): color = cm.jet_r(num / len(y)) color = plotly.colors.convert_to_RGB_255(color) + (1,) color = f"rgba{color}" name = name d = go.Scatter( mode='lines+markers', x=x, y=val, name=name, marker=dict(symbol='circle',), line=dict(dash='solid', color=color,), hovertemplate=f"{name}<br>" + '%{x} <br>' + '%{y} <br>' + "<extra></extra>", ) plot.append(d) layout = go.Layout( template=template.plotly_layout(), title=dict(text='',), xaxis=dict(title='',), yaxis=dict(title='',), ) fig = go.Figure(data=plot, layout=layout) if pic: fig.show(config=template.plotly_config()) # 作成したグラフを保存 if save: pio.write_html( fig, 'graph_y.html', auto_open=False, config=template.plotly_config(), ) pio.write_image(fig, 'graph_y.png') # 欲しい情報だけ指定 graph_y( pic=True, save=True, )
for
でy
の各グラフを取り出して、color
でそれぞれのfor
で色を決定。go.Scatter
でプロットデータを作成したのち、go.Layout
でレイアウトを決めてgo.Figure
でこれらを合体させて出力。
ここで引数のpic
とsave
が登場する。pic
をTrue
とすることで作成したグラフをブラウザ上に表示することができ、save
をTrue
にすることで作成したグラフをファイルとして保存。
グラフの保存だけしたい時は以下のようにpic
をコメントアウトしたりFalse
にしたりすればいい。
# picをコメントアウト graph_y( # pic=True, save=True, ) # picをFalseに graph_y( pic=False, save=True, ) # picのデフォルトはFalse graph_y( save=True, )
でも長くないか?
でも考えてほしい。上のコードはあまりにも長すぎないか?50行は超える。これはもっと短くしたほうが見やすいように感じる。
執筆者の使っているMacbook Pro 13インチでは51行分表示するようにフォントサイズを設定している。しかし、大半の人はもっとフォントサイズは大きいだろうから全貌が見えにくいだろう。
複数プロットになるともっとダラダラ長い
さっきの例だとコードが50行を超えていて長かった。でも100行行ってないし大丈夫だろうと思ったけど、プロットする種類が増えたらどうだろうか。要するにy
だけではなくz
という新たなデータもプロットするならどうだろうか。
新たなデータを追加
z = { 'z = x<sup>0.5</sup>': x ** 0.5, 'z = sin(0.5x)': np.sin(0.5 * x), 'z = cos(0.5x)': np.cos(0.5 * x), }
先程のy
と同じように3つのデータを追加で作成した。dict
名はz
。このデータも追加でプロットしてみる。
2つのプロットを下に続ける
# yのプロット for num, (name, val) in enumerate(y.items()): color = cm.Reds_r(num / len(y)) color = plotly.colors.convert_to_RGB_255(color) + (1,) color = f"rgba{color}" name = name d = go.Scatter( mode='lines+markers', x=x, y=val, name=name, marker=dict(symbol='circle',), line=dict(dash='solid', color=color,), hovertemplate=f"{name}<br>" + '%{x} <br>' + '%{y} <br>' + "<extra></extra>", ) plot.append(d) # zのプロット for num, (name, val) in enumerate(z.items()): color = cm.Blues_r(num / len(z)) color = plotly.colors.convert_to_RGB_255(color) + (1,) color = f"rgba{color}" name = name d = go.Scatter( mode='lines+markers', x=x, y=val, name=name, marker=dict(symbol='square',), # ここ変更 line=dict(dash='dash', color=color,), # ここ変更 hovertemplate=f"{name}<br>" + '%{x} <br>' + '%{y} <br>' + "<extra></extra>", ) plot.append(d)
さっきと同じように、y
, z
それぞれでプロットのためのgo.Scatter
を作成。単純にgo.Scatterのコード行数が2倍となる。よって、全体コードとしては以下になる。
こんなに長いコードは流石にだるい。100行には行ってないのでまだマシかもしれないが、プロット数が3つにも4つにもなったらさらに行数が必要になる。もちろんfor
でまとめることも可能だが、今回は関数を使用して簡略化してみる。
同じコードはdef
で関数化
当たり前っちゃ当たり前だけど、同じことは定式化したら楽。マニュアルとかロボットとか予め決めたり、一部を指定したらあとは自動でこなしてくれる。これをプログラミングで実装するのが関数だ(全言語がそうとは限らないかもしれないが)。
go.Scatter
を関数化
def scatter(x: np.ndarray, y: np.ndarray, name='', color=(1, 0, 0), symbol='circle', dash='solid', alpha=1.,): """横軸の値、縦軸の値より、plotlyのScatter配列を作成 Parameters ---------- x : np.ndarray 横軸の値 y : np.ndarray 縦軸の値 name : str, optional プロットの名称, by default '' color : tuple, optional プロットのrgb(R, G, B), by default (1, 0, 0) symbol : str, optional プロットのマーカー, by default 'circle' dash : str, optional プロットの線種, by default 'solid' alpha : float, optional プロットの透明度, by default 1. Returns ------- go_scatter.Scatter plotlyのgo.Scatterの配列 """ color = plotly.colors.convert_to_RGB_255(color) + (alpha,) color = f"rgba{color}" d = go.Scatter( mode='lines+markers', x=x, y=y, name=name, marker=dict(symbol=symbol), line=dict(dash=dash, color=color,), hovertemplate=f"{name}<br>" + '%{x}<br>' + '%{y}<br>' + "<extra></extra>", ) return d
まずはgo.Scatterを予め関数化。引数は以下。
x
: 横軸のデータ配列y
: 縦軸のデータ配列name
: プロットの名前(初期値:''
)color
: プロットの色。(R, G, B) = (赤, 緑, 青)
として入力。0
-1
の範囲。(初期値:(1, 0, 0)
: 赤)symbol
: プロットマーカーの種類(初期値:circle
(円形))dash
: プロット線の種類(初期値:solid
(実線))alpha
: プロット線の透明度(初期値:1.
(薄くならない))
色についてはmatplotlib
の方が慣れているのと色の種類が多かった(記憶)ので、matplotlib
のRGB方式で0
から1
の値で色を作成。しかしplotly
では0
から255
までなのでこれを変換する必要がある。
シンプルに255
をかければいいだろうけど、ちょうど関数があるので使用する。(R, G, B)でも(R, G, B, a)でも出力は(R, G, B)なので(alpha,)
で透明度の情報を付加している。
plotly.colors.convert_to_RGB_255(color) print(plotly.colors.convert_to_RGB_255((1, 0, 1))) # (R, G, B) # (255, 0, 255) print(plotly.colors.convert_to_RGB_255((1, 0, 1, 1))) # (R, G, B, a) # (255, 0, 255)
関数を呼び出すときは以下の感じで書く。この場合は直線のグラフで、名前がplot1
で色はマゼンタっぽくなり、マーカーは四角で線種は点線、透明度は0.5
で薄くなる。
返り値return
はd
としてgo.Scstter
なので、ここでもわかりやすいように戻ってきた値をd
に格納している。
d = scatter( x=[1, 2, 3], y=[10, 20, 30], name='plot1', color=(1, 0, 1), symbol='square', dash='dot', alpha=0.5, )
複数dict
から自動でプロットデータを作成する関数
def set_scatter(plot: list, dct: dict, symbol='circle', cmap=cm.Reds_r, prefix='', suffix='', dash='solid', alpha=1.,): """dictで作成した縦軸のデータをforで回してgo.Scatterの配列を作成 その後go.Scatterの配列を入力値plotのlistに入れる Parameters ---------- plot : list plotlyのgo.Figureのdataに対応するlist dct : dict 縦軸のデータを入れたdict symbol : str, optional プロットのマーカー, by default 'circle' cmap : cm.colors.LinearSegmentedColormap, optional プロットの色合いを示す、matplotlib.cmの名称, by default cm.Reds_r prefix : str, optional プロットのnameの前につける接頭辞, by default '' suffix : str, optional プロットのnameの後につける接尾辞, by default '' dash : str, optional プロットの線種, by default 'solid' alpha : float, optional プロットの透明度, by default 1. """ for num, (name, val) in enumerate(dct.items()): color = cmap(num / len(dct)) name = f"{prefix}{name}{suffix}" # さっき作成した関数を使用 d = scatter(x=x, y=val, name=name, color=color, symbol=symbol, dash=dash, alpha=alpha,) plot.append(d)
今回はdict
のデータを1つずつプロットしていくので、これも関数化してみる。引数は以下。
plot
: 作成したgo.Scatter
のデータを格納するlist。最終的にgo.Figure
に渡す。dct
: 作成したいプロットの名前と縦軸のデータの入ったdict
symbol
: プロットマーカーの種類(初期値:circle
(円形))cmap
: 引数dct
のプロットの色をmatplotlib.cm
の色で指定(初期値:cm.Reds_r
)prefix
: プロット名の初めに固定でつける接頭辞(初期値:''
)suffix
: プロット名の最後に固定でつける接尾辞(初期値:''
)dash
: プロット線の種類(初期値:solid
(実線))alpha
: プロット線の透明度(初期値:1.
(薄くならない))
まずはforでデータ数num
を0
から勘定、dct
のkeys
とvalues
を取得。num
とmatplotlib.cm
でdct
の要素ごとに色を作成。
for num, (name, val) in enumerate(dct.items()): color = cmap(num / len(dct))
prefix
とsuffix
については、dct
のkeys
に加えて統一された文言を文頭もしくは文末につけたい時に使用。dct
のkeys
の内容を変更したくない時などには便利。デフォルトが''
なので指定しなければ何もつくことはない。
ただし、prefix
を設定する時は最後に、suffix
を設定するときは初めに空白を入れないと文字がくっつくので注意。
prefix = 'prefix' name = 'name' suffix = 'suffix' name = f"{prefix}{name}{suffix}" print(name) # prefixnamesuffix prefix = 'prefix ' # 最後に半角スペース name = 'name' suffix = '\\t\\tsuffix' # 初めにタブ name = f"{prefix}{name}{suffix}" print(name) # prefix name suffix
あとはさっき作成したscatter
関数を使用すれば簡単にdict
形式のデータをgo.Scattter
に変換することが可能。最後にplot
にデータを格納することで更なる自動化が可能。
scatter
関数とset_scatter
関数を使用したグラフ
def graph_p_def(pic=False, save=False,): """作成したscatter関数、set_scatter関数を使用してy, zをグラフ化 Parameters ---------- pic : bool, optional 作成したグラフを表示するか否か, by default False save : bool, optional 作成したグラフを保存するか否か, by default False """ plot = [] # yのプロット set_scatter(plot=plot, dct=y,) # zのプロット set_scatter( plot=plot, dct=z, symbol='square', cmap=cm.Blues_r, dash='dash', ) layout = go.Layout( template=template.plotly_layout(), title=dict(text='',), xaxis=dict(title='',), yaxis=dict(title='',), ) fig = go.Figure(data=plot, layout=layout) if pic: fig.show(config=template.plotly_config()) # 作成したグラフを保存 if save: pio.write_html( fig, 'graph_p_def.html', auto_open=False, config=template.plotly_config(), ) pio.write_image(fig, 'graph_p_def.png') graph_p_def( pic=True, save=True, )
上で解説したscatter
関数とset_scatter
関数を使用したグラフコードが上。だいぶスッキリしたんじゃないだろうか。これで50行は切った。このコードでできるグラフは先ほどと同じだが一応載せておく。
レイアウトもグラフ保存も関数化
さっきのコードでプロット部分を関数を使用して簡略化することができた。しかし、よくよく考えればレイアウト部分も関数化できそうだし、グラフの保存も関数化できそうだ。
ここではレイアウトとグラフ保存の関数化も行う。
go.Layout
の関数化
def set_layout(title='', xtitle='', ytitle='', xrange=None, yrange=None, xtype='linear', ytype='linear'): """go.Layoutの設定 Parameters ---------- title : str, optional グラフタイトル, by default '' xtitle : str, optional 横軸ラベル, by default '' ytitle : str, optional 縦軸ラベル, by default '' xrange : list or tuple, optional 横軸の初期表示範囲, by default None yrange : list or tuple, optional 縦軸の初期表示範囲, by default None xtype : str, optional 横軸のタイプ(logかlinearなど), by default 'linear' ytype : str, optional 縦軸のタイプ(logかlinearなど), by default 'linear' Returns ------- go._layout.Layout plotlyのgo.Layout配列 """ layout = go.Layout( template=template.plotly_layout(), title=dict(text=title,), xaxis=dict(title=xtitle, range=xrange, type=xtype,), yaxis=dict(title=ytitle, range=yrange, type=ytype,), ) return layout
レイアウトについてはgo.Layout
で指定することができるが、設定項目がエグいくらい多い。そこで、ここでは普段から執筆者がよく使う設定のみを引数として使用する。引数は以下。
title
: グラフタイトル(初期値:''
)xtitle
: 横軸ラベル(初期値:''
)ytitle
: 縦軸ラベル(初期値:''
)xrange
: 横軸の初期表示範囲(初期値:None
)yrange
: 縦軸の初期表示範囲(初期値:None
)xtype
: 横軸の形式(線形かlogかとか)(初期値:'linear'
)ytype
: 縦軸の形式(線形かlogかとか)(初期値:'linear'
)
使い方はscatterの時と同様で、以下のように書けばいい。
layout = set_layout( title='これはタイトル', xtitle='X', ytitle='Y', xrange=(-0.2, 10), yrange=(-1.2, 1.2), )
設定しなくていい項目は初期値があるなら書かなくてもいい。
pio.write_
を関数化
def set_save(fig, file_name: str, img_extension='png'): pio.write_html( fig, f"{file_name}.html", auto_open=False, config=template.plotly_config(), ) pio.write_image(fig, f"{file_name}.{img_extension}")
グラフの保存はpio.write_
で行っているが、グラフの保存に必要なのはどのグラフをどのファイル名で保存するかという2点。ここでは拡張子を別で指定できるようにしているが、重要なのはこの2点。
なので、引数に2点+拡張子を入れた関数を作成。もちろん静止画がいらない場合はpio.write_image
は決して構わないし、htmlがいらないならpio.write_html
を消して構わない。
レイアウトとグラフ保存を関数化したグラフ
a = { 'a = sin(x)': np.sin(x), 'a = cos(x)': np.cos(x), 'a = tan(x)': np.tan(x), }
ということで、レイアウトとグラフ保存を関数化した後のグラフを作成する。データは少し変えて三角関数のみとした。
def graph_pls_def(pic=False, save=False): """プロット、レイアウト、保存を設定した関数からグラフを作成 Parameters ---------- pic : bool, optional 作成したグラフを表示するか否か, by default False save : bool, optional 作成したグラフを保存するか否か, by default False """ plot = [] set_scatter( plot=plot, dct=a, symbol='hexagram', cmap=cm.cool, dash='dashdot', alpha=0.5, ) layout = set_layout( title='trigonometric functions: 三角関数', xtitle='x', ytitle='y', xrange=(-0.2, 10), yrange=(-1.2, 1.2), ) fig = go.Figure(data=plot, layout=layout) if pic: fig.show(config=template.plotly_config()) if save: set_save(fig=fig, file_name='graph_pls_def', img_extension='png') graph_pls_def( pic=True, save=True, )
かなりスッキリした。これでパッと見の印象も良くなる。ここではset_scatter
などの関数には直接a
などの引数を入れているが、もちろんこれもgraph_pls_def
の引数とすれば、graph_pls_def
自体を使いまわすことが簡単になる。これについては最後に行う。
色をRGBとstr
の入力でそれぞれ自動計算
話がガラリと変わるが、プロットの色をRGBのtuple
でも'red'
のようなstr
でも対応させる方法がないだろうかということを知った。最後はこれについて解説する。
plotly
の0-255変換にはstr
は入れられない
base_color = 'limegreen' # plotly.colors.convert_to_RGB_255は(R, G, B)を0-1から0-255にする関数 # よって色のstrを入れることはできない plotly_color = plotly.colors.convert_to_RGB_255(base_color) # TypeError: can't multiply sequence by non-int of type 'float'
ことの発端はplotly.colors.convert_to_RGB_255
にstr
での色を入れたらエラーが出たということ。今まではmatplotlib.cm
のカラーマップ用の色を使用していたが、'red'
のように色を直接指定したい時があった。
しかし上にあるようにstr
でありfloat
ではないのでエラーが出る。float
のtuple
だとこのエラーは出ずに正常に処理される。
# R, G, Bを設定すると計算可能 plotly_color = plotly.colors.convert_to_RGB_255((1, 0.5, 0)) print(plotly_color) # (255, 128, 0)
matplotlib
でstr
の色をRGBに変換
# matplotlib.colors.ColorConverter.to_rgbで色のstrをrgbに変換することが可能 rgb_color = matplotlib.colors.ColorConverter.to_rgb(base_color) print(rgb_color) # (0.19607843137254902, 0.803921568627451, 0.19607843137254902) print(type(rgb_color)) # <class 'tuple'>
そんな中、matplotlib
でstr
の色をRGBに変換できる関数を見つけた。matplotlib.colors.ColorConverter.to_rgb
だ。これにstr
の色を入れることでその色が0
から1
の間のRGBとして出力される。
これならplotlyの255RGB変換が可能なので、変換してみる。
# (R, G, B)の配列で出力できたのでplotly用に変換することが可能に plotly_color = plotly.colors.convert_to_RGB_255(rgb_color) print(plotly_color) # (50, 205, 50)
できた。一応確認のためにグラフ化してみる。
色をRGBとstr
の入力でそれぞれ自動計算したscatter
try: # colorが(R, G, B)形式の場合 color = plotly.colors.convert_to_RGB_255(color) except TypeError: # colorが色のstrの場合 color = matplotlib.colors.ColorConverter.to_rgb(color)
これまでの処理でわかったことをまとめると以下。
- (R, G, B)の色となっている場合:
plotly.colors.convert_to_RGB_255(color)
str
の色となっている場合:matplotlib.colors.ColorConverter.to_rgb(color)
なので上のコードで書いたように、try
文でエラーが出るか否かで処理を分岐。適切な処理が行われるようにした。以下でgo.Scatter
をリニューアル。
def scatter_renewal(x: np.ndarray, y: np.ndarray, name='', color=cm.jet, symbol='circle', dash='solid', alpha=1.,): """横軸の値、縦軸の値より、plotlyのScatter配列を作成 Parameters ---------- x : np.ndarray 横軸の値 y : np.ndarray 縦軸の値 name : str, optional プロットの名称, by default '' color : tuple, optional プロットのrgba(R, G, B, a), by default (1, 0, 0) symbol : str, optional プロットのマーカー, by default 'circle' dash : str, optional プロットの線種, by default 'solid' alpha : float, optional プロットの透明度, by default 1. Returns ------- go_scatter.Scatter plotlyのgo.Scatterの配列 """ try: # colorが(R, G, B)形式の場合 color = plotly.colors.convert_to_RGB_255(color) except TypeError: # colorが色のstrの場合 color = matplotlib.colors.ColorConverter.to_rgb(color) color = f"rgba{color + (alpha,)}" d = go.Scatter( mode='lines+markers', x=x, y=y, name=name, marker=dict(symbol=symbol), line=dict(dash=dash, color=color,), hovertemplate=f"{name}<br>" + '%{x}<br>' + '%{y}<br>' + "<extra></extra>", ) return d
色をRGBとstr
の入力でそれぞれ自動計算したグラフ
def graph_color_renewal(x: np.ndarray, y: np.ndarray, file_name: str, name='', color=(1, 0, 0), symbol='circle', dash='solid', alpha=1., title='', xtitle='', ytitle='', xrange=None, yrange=None, xtype='linear', ytype='linear', img_extension='png', pic=False, save=False): """x, yの値からグラフをプロット Parameters ---------- x : np.ndarray 横軸の値 y : np.ndarray 縦軸の値 file_name : str グラフの保存名 name : str, optional プロットの名称, by default '' color : tuple, optional プロットの色。(R, G, B)か色のstrで指定, by default (1, 0, 0) symbol : str, optional プロットのマーカー, by default 'circle' dash : str, optional プロットの線種, by default 'solid' alpha : float, optional プロットの透明度, by default 1. title : str, optional グラフタイトル, by default '' xtitle : str, optional 横軸ラベル, by default '' ytitle : str, optional 縦軸ラベル, by default '' xrange : tuple, optional 横軸の表示範囲, by default None yrange : tuple, optional 縦軸の表示範囲, by default None xtype : str, optional 横軸のタイプ, by default 'linear' ytype : str, optional 縦軸のタイプ, by default 'linear' img_extension : str, optional グラフの静止画の拡張子, by default 'png' pic : bool, optional 作成したグラフを表示するか否か, by default False save : bool, optional 作成したグラフを保存するか否か, by default False """ plot = [] d = scatter_renewal( x=x, y=y, name=name, color=color, symbol=symbol, dash=dash, alpha=alpha, ) plot.append(d) layout = set_layout( title=title, xtitle=xtitle, ytitle=ytitle, xrange=xrange, yrange=yrange, xtype=xtype, ytype=ytype ) fig = go.Figure(data=plot, layout=layout) if pic: fig.show(config=template.plotly_config()) if save: set_save(fig=fig, file_name=file_name, img_extension=img_extension)
最後に総復習として、これまでの関数の引数を全てグラフの引数で指定しつつ、色をRGBとstr
で指定する。なので、graph_color_renewal
の引数は半端ないことになっているが、その代わりにグラフの中身はかなり少なくなっているだろう。
プロットデータをdct
で入れる場合はdct
用で処理が必要だけど、ここではとりあえず割愛する。引数は以下。
x
: 横軸の値y
: 縦軸の値file_name
: グラフの保存名name
: プロットの名称(初期値:''
)color
: プロットの色。(R, G, B)か色のstrで指定(初期値:(1, 0, 0)
)symbol
: プロットのマーカー(初期値:'circle'
)dash
: プロットの線種(初期値:'solid'
)alpha
: プロットの透明度(初期値: 1.)title
: グラフタイトル(初期値:''
)xtitle
: 横軸ラベル(初期値:''
)ytitle
: 縦軸ラベル(初期値:''
)xrange
: 横軸の表示範囲(初期値:None
)yrange
: 縦軸の表示範囲(初期値:None
)xtype
: 横軸のタイプ(初期値:'linear'
)ytype
: 縦軸のタイプ(初期値:'linear'
)img_extension
: グラフの静止画の拡張子(初期値:'png'
)pic
: 作成したグラフを表示するか否か(初期値:False
)save
: 作成したグラフを保存するか否か(初期値:False
)
で、引数が多いから大変そうかもしれないが、実際に使用する際には引数に必要な情報を入れるだけでいいのでシンプルになる。
以下で関数呼び出しの一例を示す。ここでは1引数ごとに改行しているがからかなり行数をとっているが、もちろん引数の後に次の引数を書いてもいい。
# 色をRGBで指定 color = (1, 0, 1) # マゼンタっぽい色 graph_color_renewal( x=x, y=a['a = sin(x)'], file_name='graph_color_renewal_rgb', name='RGB=101', color=color, title='R : G : B = 1 : 0 : 1', xtitle='x', ytitle='y', img_extension='png', pic=True, save=True, )
# 色をstrで指定 color = 'darkviolet' # 暗い紫色 graph_color_renewal( x=x, y=a['a = sin(x)'], file_name='graph_color_renewal_str', name=f"color={color}", color=color, title=f"color = {color}", xtitle='x', ytitle='y', img_extension='png', pic=True, save=True, )
関数化で楽ができそう
今回は最近行っているplotlyの関数化について解説した。関数化するのは結構面倒だけど、一回作成すると後でもサクッと使用できて全体コードの一貫性とシンプルかが見込める。
上であげたコードではまだ関数化できる、繰り返し処理があるのでまたなんとかして関数化して簡単にしたい。
しかし、重要なのはわかりやすさと簡潔さ。いくら関数化できたとしても使いにくかったり見にくかったら意味がない。昔の執筆者がそうで、1行でなるべくまとめようとしすぎて久しぶりの自分が見たらなんのこっちゃか。
どこかで見た言葉で「3日後の自分は他人」がある。プログラミング経験者でも過去の自分でもはたまたプログラミング初心者でもわかりやすいコードを書く必要があると感じる。まだまだ成長過程。
関連記事
-
-
【python&関数化】defとかargsとかを使って関数を作成する
続きを見る
-
-
【plotly&go.Scatter】plotlyの散布図グラフの描き方
続きを見る
-
-
【plotly&ボタン】plotlyのupdatemenusにbuttonsを追加
続きを見る
-
-
【plotly&スライダー】plotlyのslidersにスライダーを追加
続きを見る