こんな人にオススメ
matplotlib.pyplot
、plt
のマーカーにはどんな種類があるの?
三角とか四角とか色んなマーカーを使ってみたい。
ということで、今回はplt
のマーカー一覧をグラフ化して見やすくする。plt
のマーカーの種類なんて腐るほどの記事が挙がっているけど、自分用の備忘録としても記録しておく。
なお、plotly
でも以下の記事で同じようにマーカー一覧をグラフ化している。
-
-
【plotly&マーカー】plotlyのマーカーのシンボル
続きを見る
python環境は以下。
- Python 3.9.7
- numpy 1.21.2
- matplotlib 3.4.3
作成したコード全文
下準備
import sys import numpy as np import matplotlib.pyplot as plt import matplotlib.cm as cm import matplotlib from matplotlib.lines import Line2D sys.path.append('../../') import plt_layout_template plt.ioff()
まずは下準備としてのimport
関連。今回はマーカーを自動で取得するのでmatplotlib
関連が多め。plt_layout_template
は自作のテンプレートで、これをimport
しておくだけでキレイなグラフが描ける。
-
-
【pltテンプレート】matplotlib.pyplotのグラフ作成テンプレート
続きを見る
また、plt.ioff()
はVisual Studio Codeの拡張機能「Code Runner」を使用するために設定。デフォルトではioff()
になっているけど、テンプレートでion()
にしているから設定している。
ion()
のままだとCode Runnerの実行でグラフが表示されない。保存するだけならion()
のままでも問題ない。
plt
のマーカー一覧を文字で
markers = Line2D.markers print(markers) # {'.': 'point', ',': 'pixel', 'o': 'circle', 'v': 'triangle_down', '^': 'triangle_up', '<': 'triangle_left', '>': 'triangle_right', '1': 'tri_down', '2': 'tri_up', '3': 'tri_left', '4': 'tri_right', '8': 'octagon', 's': 'square', 'p': 'pentagon', '*': 'star', 'h': 'hexagon1', 'H': 'hexagon2', '+': 'plus', 'x': 'x', 'D': 'diamond', 'd': 'thin_diamond', '|': 'vline', '_': 'hline', 'P': 'plus_filled', 'X': 'x_filled', 0: 'tickleft', 1: 'tickright', 2: 'tickup', 3: 'tickdown', 4: 'caretleft', 5: 'caretright', 6: 'caretup', 7: 'caretdown', 8: 'caretleftbase', 9: 'caretrightbase', 10: 'caretupbase', 11: 'caretdownbase', 'None': 'nothing', None: 'nothing', ' ': 'nothing', '': 'nothing'}
ということで、plt
のマーカー一覧を表示すると上のようになる。出力はdict
でkeys
の表現とvalues
の表現、どちらで指定しても指定した記号の表現となる。
見づらいのでfor
で回して表示してみる。
for marker in markers.items(): print(marker) # ('.', 'point') # (',', 'pixel') # ('o', 'circle') # ('v', 'triangle_down') # ('^', 'triangle_up') # ('<', 'triangle_left') # ('>', 'triangle_right') # ('1', 'tri_down') # ('2', 'tri_up') # ('3', 'tri_left') # ('4', 'tri_right') # ('8', 'octagon') # ('s', 'square') # ('p', 'pentagon') # ('*', 'star') # ('h', 'hexagon1') # ('H', 'hexagon2') # ('+', 'plus') # ('x', 'x') # ('D', 'diamond') # ('d', 'thin_diamond') # ('|', 'vline') # ('_', 'hline') # ('P', 'plus_filled') # ('X', 'x_filled') # (0, 'tickleft') # (1, 'tickright') # (2, 'tickup') # (3, 'tickdown') # (4, 'caretleft') # (5, 'caretright') # (6, 'caretup') # (7, 'caretdown') # (8, 'caretleftbase') # (9, 'caretrightbase') # (10, 'caretupbase') # (11, 'caretdownbase') # ('None', 'nothing') # (None, 'nothing') # (' ', 'nothing') # ('', 'nothing')
マーカーは5種類
実はマーカーは大きく分けると5種類ある。詳しくは公式の「matplotlib.markers」に書いてあるけど、リストにすると以下。
- 「o」や「s」など規定の記号
- 「$...$」で囲んだ$\LaTeX$表現
- 座標を指定して線でつなぐ(verts)
matplotlib.path.Path
で作成できる図形(numsides, num, angle)
の形式で作成できる図形
一般的なサイトには1, 2が書かれている事多いし、実際に1と2で大半のマーカーはできると思う。
さっきのfor
文での出力は1に該当する。2の$\LaTeX$形式は自作する形になるので以下で追加しておく。
markers['$\\\\alpha$'] = 'alpha' # アルファ markers['$\\\\times$'] = 'multiplication' # 掛け算記号 markers[r'$\\sum_{k=1}^n k^2$'] = 'sum' # シグマ記号
追加分も含めた出力は以下。
for marker in markers.items(): print(marker) # ('.', 'point') # (',', 'pixel') # ('o', 'circle') # ('v', 'triangle_down') # ('^', 'triangle_up') # ('<', 'triangle_left') # ('>', 'triangle_right') # ('1', 'tri_down') # ('2', 'tri_up') # ('3', 'tri_left') # ('4', 'tri_right') # ('8', 'octagon') # ('s', 'square') # ('p', 'pentagon') # ('*', 'star') # ('h', 'hexagon1') # ('H', 'hexagon2') # ('+', 'plus') # ('x', 'x') # ('D', 'diamond') # ('d', 'thin_diamond') # ('|', 'vline') # ('_', 'hline') # ('P', 'plus_filled') # ('X', 'x_filled') # (0, 'tickleft') # (1, 'tickright') # (2, 'tickup') # (3, 'tickdown') # (4, 'caretleft') # (5, 'caretright') # (6, 'caretup') # (7, 'caretdown') # (8, 'caretleftbase') # (9, 'caretrightbase') # (10, 'caretupbase') # (11, 'caretdownbase') # ('None', 'nothing') # (None, 'nothing') # (' ', 'nothing') # ('', 'nothing') # ('$\\\\alpha$', 'alpha') # ('$\\\\times$', 'multiplication') # ('$\\\\sum_{k=1}^n k^2$', 'sum')
規定のマーカーとLaTeX表現をグラフ化
まずは規定のマーカーと$\LaTeX$表現について。変数markers
にこれらの情報は入れてあるので、あとはグラフ化するのみ。
左上から下に向かってマーカーが表現され、全体の半分の数まできたら右上に移動して再度、下方向に並んで行くようにした。
プロットの左にあるのがプロットで使用した記号で、その名称をプロットの上に傾けて表現した。右下の$\LaTeX$はごちゃごちゃして見づらい。
def graph(): fig, ax = plt.subplots(1, 1, figsize=(16, 10)) ax.set_axis_off() # 軸を非表示に fig.tight_layout() # 余白を小さく ax.set_title('Line2D.markers') for num, (symbol, name) in enumerate(markers.items()): length = len(markers) half = length // 2 color = cm.jet(num / length) # 色を作成 x = np.array((1, 2, 3)) + (num // half) * 3 # 左から右に並ぶように y = np.array((1, 2, 3)) - num % half # 上から下に並ぶように ax.plot(x, y, marker=symbol, ms=15, color=color) # グラフにテキストを追加 ax.text(min(x), min(y), f"{symbol} ", ha='right', va='center') ax.text(min(x), min(y), name, ha='left', va='bottom', rotation=10) fig.savefig('default_latex.png') plt.show() graph()
3列にしたい場合はhalf
の部分を//3
にすればいい。ただし、数が偶数なので3列からちょっとはみ出て4列になってしまう。そこは調節してほしい。
また、左上から下方向に作成したが、x
とy
の//
と%
を入れ替えて調節すると左上から右へ1つ行ってすぐに左下に行くようにもできる。
verts
, Path
, numsides
のグラフ化のための関数
def graph_from_dct(title, dct, save_name): fig, ax = plt.subplots(1, 1, figsize=(16, 10)) ax.set_axis_off() # 軸を非表示に fig.tight_layout() # 余白を小さく ax.set_title(title) # 入力したdictで回してグラフ化 for num, (name, val) in enumerate(dct.items()): x = np.array((1, 2, 3)) y = np.array((1, 2, 3)) - num ax.plot(x, y, marker=val, ms=15, color='black') ax.text(min(x), min(y), f" {name}", ha='left', va='top') fig.savefig(save_name) plt.show()
続いては残りの3項目、verts
, Path
, numsides
について。これらについてはmarkers
と一緒にしてもよかったけど、場合分けとして分けた。
大体のサイトだとこのverts
, Path
, numsides
の解説がない。ここでも深くまではやらないけど、こんなこともできるんだくらいに見てほしい。
graph_from_dct
関数ではマーカーをdictで指定して、それを1マーカーずつズラしながらプロットするというもの。あとはテキストをいい感じに追加した。
verts
をグラフ化
ということで、まずはverts
からグラフ化する。verts
は(x, y)の形式で座標を指定することで、この座標に従ってプロットされるというもの。
座標の設定をうまくすることで色んな図形を作成することができる。上だと三角形とタグのようなものをグラフにしてみた。
指定した座標を直線でつなぐので、曲線を使用する図形はマーカーにはできないが、簡単なものはこれで作成可能。
verts_dct = { 'triangle': ((-1, -1), (1, -1), (1, 1), (-1, -1)), 'tag': [[-1, -1], [1, -1], [1, 1], [-1, 1], [-2, 0]], } graph_from_dct(title='verts', dct=verts_dct, save_name='verts')
path
をグラフ化
続いてはpath
。こちらはmatplotlib.path.Path
から指定される図形を示す。詳細は公式サイト
に載っているが、具体的にプロットしたのが上。
パックマンっぽいのとカマボコ状のもの、そして円形をプロットしてみた。まあ円のmarker
を指定したい時は普通にcircle
にすればいい。
path_dct = { 'Pac-Man': matplotlib.path.Path.wedge(90, 0), 'kamaboko': matplotlib.path.Path.arc(theta1=0, theta2=180), 'circle': matplotlib.path.Path.circle(center=(8, 0), radius=5), } graph_from_dct(title='path', dct=path_dct, save_name='path')
numsides
をグラフ化
最後はnumsides
を指定してグラフ化。これは3つの数字で図形を作成するというもの。各数字はtuple
で(numsides, 0, angle)
のように指定する。
numsides
: エッジの個数- 第二引数
- 0: 多角形
- 1: 星に近い図形
- 2: アスタリスク
- angle: 回転させる角度
同じnumsides=8
でも第二引数が1か2かで塗りつぶしがあるかないかが異なったりする。一部はtri_up
などの記号で指定したのと同じになる。
しかし、もうちょっと複雑な図形にしようとするとこのnumsides
は使えるだろう。
numsides_dct = { '1-0-30': (1, 0, 30), '3-0-0': (3, 0, 0), '3-0-30': (3, 0, 30), '8-0-30': (8, 0, 0), '1-1-30': (1, 1, 30), '3-1-0': (3, 1, 0), '3-1-30': (3, 1, 30), '8-1-30': (8, 1, 0), '1-2-30': (1, 2, 30), '3-2-0': (3, 2, 0), '3-2-30': (3, 2, 30), '8-2-30': (8, 2, 0), } graph_from_dct(title='numsides', dct=numsides_dct, save_name='numsides')
ちょっと深掘ると新しい世界
ということで、今回はplt
を使用して色々なマーカーを見てきた。既に書いたけど、大体のサイトだと基本的なマーカーしか紹介していない。
しかし、今回のようにもうちょっと深掘りをしてみると他の方法も見えてきて結構面白い。
また何かの機会にちょっと深掘りをするような記事を作成してみたい。
関連記事
-
-
【plotly&go.Scatter】plotlyの散布図グラフの描き方
続きを見る
-
-
【plt vs plotly】matplotlibとgoでグラフの比較
続きを見る
-
-
【plt&subplot】pythonのpltで複数グラフを1つの画像に描く
続きを見る
-
-
【plotly&コッホ曲線】フラクタル図形の雪の結晶をスライダーで作成してみる
続きを見る