はじめに
Matplotlibライブラリを利用して、矢印プロットを作成します。
【前の内容】
【目次】
quiver関数の矢印色の設定:2次元の場合
Matplotlibライブラリのquiver関数で矢印を描画できます。前回は、2次元の場合の矢のサイズ・形状に関する引数を確認しました。今回は、矢の色に関する引数を確認します。
利用するライブラリを読み込みます。
# 利用ライブラリ import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation
矢印の作図
まずは、2次元の場合の矢印の座標・長さに関する引数を簡単に確認します。
詳しくは「矢印プロットの作図【ゼロつく1のノート(Python)】 - からっぽのしょこ」を参照してください。
座標と移動量を指定して、矢印を描画します。
# 座標・移動量を指定 x, y = 0.0, 1.0 u, v = 3.0, 2.0 # 枠色・面色・枠線幅を指定 fc = 'lightgreen' ec = 'orange' lw = 2.0 # ラベル用の文字列を作成 str_fc = 'None' if fc == None else "'" + fc + "'" str_ec = 'None' if ec == None else "'" + ec + "'" # 2Dベクトルを作図 fig, ax = plt.subplots(figsize=(6, 5), facecolor='white') ax.scatter(x, y, s=100, label='(X, Y)') # 始点 ax.scatter(x+u, y+v, s=100, label='(X+U, Y+V)') # 終点 ax.quiver(x, y, u, v, facecolor=fc, edgecolor=ec, linewidth=lw, units='dots', width=6, headwidth=3, headlength=5, headaxislength=4.5, angles='xy', scale_units='xy', scale=1, label='({: .2f}, {: .2f}, {: .2f}, {: .2f})'.format(x, y, u, v)) # 矢印 ax.set_xticks(ticks=np.arange(np.floor(x-abs(u))-1, np.ceil(x+abs(u))+2)) ax.set_yticks(ticks=np.arange(np.floor(y-abs(v))-1, np.ceil(y+abs(v))+2)) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('facecolor='+str_fc+', edgecolor='+str_ec+', linewidth='+str(lw), loc='left', fontsize=10) fig.suptitle('pyplot.quiver(X, Y, U, V)', fontsize=15) ax.grid() ax.legend() ax.set_aspect('equal') plt.show()
2次元ベクトルの場合は、第1・2引数に始点の座標 X, Y
、第3・4引数に移動量 U, V
を指定します。終点の座標は X + U, Y + V
になります。
angles='xy'
、scale_units='xy'
、scale=1
を指定すると、指定した座標の通りに描画されます。デフォルトでは矢印の長さ(終点の座標)が自動調整されます。
width
引数は矢全体の幅、headwidth
引数は矢頭の幅、headlength
引数は矢頭の最大幅までの長さ、headaxislength
引数は矢頭の長さです。
終点の座標と矢の長さの関係については「矢印の色の設定」を参照してください。
(ラベル用の文字列でごにょごにょやってるのは、文字列を表すためにクォーテーションマーク '
を前後に追加して、しかし None
のときは追加しない拘りのためです。矢印の作図自体には不要な処理です。)
色に関する引数
次からは、矢印の色に関する引数を確認していきます。
cmap引数
cmap
引数で矢の色のグラデーションを設定できます。
引数の値を変更した矢印を並べて描画します。
・作図コード(クリックで展開)
# 矢印の数を指定 n = 20 # カラーマップ・枠色・枠線幅を指定 cmap = 'viridis' ec = None lw = 0.0 # x軸方向の移動量を指定 u = 3.0 # 座標・移動量を作成 os = np.repeat(0, repeats=n) ys = np.arange(n) us = np.repeat(u, repeats=n) # グラデーション用の値を指定 cs = ys**2 # ラベル用の文字列を作成 str_cmap = 'None' if cmap == None else "'" + cmap + "'" str_ec = 'None' if ec == None else "'" + ec + "'" # 2Dベクトルを作図 fig, ax = plt.subplots(figsize=(6, 8), facecolor='white') quiv = ax.quiver(os, ys, us, os, cs, cmap=cmap, edgecolor=ec, linewidth=lw, units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, angles='xy', scale_units='xy', scale=1) # 矢印 for i in range(n): ax.text(0, i, s='C='+str(cs[i])+' ', size=10, ha='right', va='center') # 引数ラベル ax.set_xticks(ticks=np.arange(u+1)) ax.set_yticks(ticks=np.arange(n)) ax.set_xlim(-6, np.ceil(u)+1) ax.set_ylim(-1, n) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('cmap='+str_cmap+', edgecolor='+str_ec+', linewidth='+str(lw), loc='left', fontsize=10) fig.suptitle('pyplot.quiver(cmap)', fontsize=15) plt.colorbar(quiv) ax.grid(axis='x') ax.set_aspect('equal') plt.show()
第5引数にグラデーション用の値、cmap
引数にカラーマップ名を指定します。デフォルトは viridis
です。
使用できるカラーマップについては「Choosing Colormaps in Matplotlib — Matplotlib 3.7.2 documentation」を参照してください。
引数の値を変更した矢印のアニメーションを作成します。
・作図コード(クリックで展開)
# フレーム数を指定 n = 101 # グラデーション用の値の範囲を指定 cs = np.linspace(start=-10, stop=10, num=n) # カラーマップ・枠色・枠線幅を指定 cmap = None ec = None lw = 0.0 # x軸方向の移動量を指定 u = 3.0 # ラベル用の文字列を作成 str_cmap = 'None' if cmap == None else "'" + cmap + "'" str_ec = 'None' if ec == None else "'" + ec + "'" # グラフオブジェクトを初期化 fig, ax = plt.subplots(figsize=(7, 3), facecolor='white') fig.suptitle('pyplot.quiver(cmap)', fontsize=15) # カラーバー描画用のダミーを作成 tmp = ax.quiver(0, 0, u, 0, 0, cmap=cmap, clim=(cs.min(), cs.max()), edgecolor=ec, linewidth=lw, units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, angles='xy', scale_units='xy', scale=1) # 矢印 fig.colorbar(tmp) # 作図処理を関数として定義 def update(i): # 前フレームのグラフを初期化 plt.cla() # 2Dベクトルを作図 ax.quiver(0, 0, u, 0, cs[i], cmap=cmap, clim=(cs.min(), cs.max()), edgecolor=ec, linewidth=lw, units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, angles='xy', scale_units='xy', scale=1) # 矢印 ax.text(0, 0, s='C={: .1f}'.format(cs[i])+' ', size=10, ha='right', va='center') # 引数ラベル ax.set_xticks(ticks=np.arange(u+1)) ax.set_yticks(ticks=[0]) ax.set_xlim(-3, np.ceil(u)+1) ax.set_ylim(-1, 1) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('cmap='+str_cmap+', edgecolor='+str_ec+', linewidth='+str(lw), loc='left', fontsize=10) ax.grid(axis='x') ax.set_aspect('equal') # gif画像を作成 ani = FuncAnimation(fig=fig, func=update, frames=n, interval=100) # gif画像を保存 ani.save(filename='2d_quiver_cmap.gif')
作図処理をupdate()
として定義して、FuncAnimation()
でgif画像を作成します。
フレームごとにカラーバーが表示されないように、update()
の外でダミーのグラフを使って設定しておきます。( if
文で初回だけ処理しようとしても2つ表示されてしまいます。なぜ?)
clim
引数にグラデーションの最小値・最大値を指定できます。
facecolor引数
color, facecolor
引数で矢の内側の色を設定できます。
引数の値を変更した矢印を並べて描画します。
・作図コード(クリックで展開)
# 面色を指定 fcs = [ 'purple', 'green', 'pink', 'yellow', 'lightblue', 'red', 'lightgreen', 'white', '#F8C46E', '#DAC4AA' ] # 矢印の数を設定 n = len(fcs) # 枠色・枠線幅を指定 ec = None lw = 0.0 # x軸方向の移動量を指定 u = 3.0 # 座標・移動量を作成 os = np.repeat(0, repeats=n) ys = np.arange(n) us = np.repeat(u, repeats=n) # ラベル用の文字列を作成 str_ec = 'None' if ec == None else "'" + ec + "'" # 2Dベクトルを作図 fig, ax = plt.subplots(figsize=(6, 6), facecolor='white') ax.quiver(os, ys, us, os, facecolor=fcs, edgecolor=ec, linewidth=lw, units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, angles='xy', scale_units='xy', scale=1) # 矢印 for i in range(n): str_fc = 'None' if fcs[i] == None else "'" + fcs[i] + "'" ax.text(0, i, s='facecolor=' + str_fc + ' ', size=10, ha='right', va='center') # 引数ラベル ax.set_xticks(ticks=np.arange(u+1)) ax.set_yticks(ticks=np.arange(n)) ax.set_xlim(-6, np.ceil(u)+1) ax.set_ylim(-1, n) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('edgecolor='+str_ec+', linewidth='+str(lw), loc='left', fontsize=10) fig.suptitle('pyplot.quiver(facecolor)', fontsize=15) ax.grid(axis='x') ax.set_aspect('equal') plt.show()
facecolor
または省略形の fc, color
引数は、矢全体の塗りつぶし色です。色名やカラーコードを指定できます。デフォルトは黒色で、None
を指定するとMatplotlibで良く使われるデフォルト色( C0
)になります。
・作図コード(クリックで展開)
# 面色を指定 fcs = [None, 'C0'] # 矢印の数を設定 n = len(fcs) # 枠色・枠線幅を指定 ec = None lw = 0.0 # x軸方向の移動量を指定 u = 3.0 # ラベル用の文字列を作成 str_ec = 'None' if ec == None else "'" + ec + "'" # 2Dベクトルを作図 fig, ax = plt.subplots(figsize=(6, 3), facecolor='white') for i in range(n): ax.quiver(0, i, u, 0, facecolor=fcs[i], edgecolor=ec, linewidth=lw, units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, angles='xy', scale_units='xy', scale=1) # 矢印 str_fc = 'None' if fcs[i] == None else "'" + fcs[i] + "'" ax.text(0, i, s='facecolor=' + str_fc + ' ', size=10, ha='right', va='center') # 引数ラベル ax.set_xticks(ticks=np.arange(u+1)) ax.set_yticks(ticks=np.arange(n)) ax.set_xlim(-6, np.ceil(u)+1) ax.set_ylim(-1, n) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('edgecolor='+str_ec+', linewidth='+str(lw), loc='left', fontsize=10) fig.suptitle('pyplot.quiver(facecolor)', fontsize=15) ax.grid(axis='x') ax.set_aspect('equal') plt.show()
配色用のリストや配列に None
が含まれると処理できないので、for
文を使って1つずつ設定を変えて描画します。
edgecolor引数
edgecolor
引数で矢の枠線の色を設定できます。
引数の値を変更した矢印を並べて描画します。
・作図コード(クリックで展開)
# 枠色を指定 ecs = [ 'purple', 'green', 'pink', 'yellow', 'lightblue', 'red', 'lightgreen', 'white', '#F8C46E', '#DAC4AA' ] # 矢印の数を設定 n = len(ecs) # 面色・枠線幅を指定 fc = 'white' lw = 2.0 # x軸方向の移動量を指定 u = 3.0 # 座標・移動量を作成 os = np.repeat(0, repeats=n) ys = np.arange(n) us = np.repeat(u, repeats=n) # ラベル用の文字列を作成 str_fc = 'None' if fc == None else "'" + fc + "'" # 2Dベクトルを作図 fig, ax = plt.subplots(figsize=(6, 6), facecolor='white') ax.quiver(os, ys, us, os, facecolor=fc, edgecolor=ecs, linewidth=lw, units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, angles='xy', scale_units='xy', scale=1) # 矢印 for i in range(n): str_ec = 'None' if ecs[i] == None else "'" + ecs[i] + "'" ax.text(0, i, s='edgecolor=' + str_ec + ' ', size=10, ha='right', va='center') # 引数ラベル ax.set_xticks(ticks=np.arange(u+1)) ax.set_yticks(ticks=np.arange(n)) ax.set_xlim(-6, np.ceil(u)+1) ax.set_ylim(-1, n) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('facecolor='+str_fc+', linewidth='+str(lw), loc='left', fontsize=10) fig.suptitle('pyplot.quiver(edgecolor)', fontsize=15) ax.grid(axis='x') ax.set_aspect('equal') plt.show()
edgecolor
または省略形の ec
引数は、矢の枠の色です。色名やカラーコードを指定できます。デフォルトや None
を指定した場合は白色になります。
・作図コード(クリックで展開)
# 枠色を指定 ecs = [None, 'C0'] # 矢印の数を設定 n = len(ecs) # 面色・枠線幅を指定 fc = 'white' lw = 2.0 # x軸方向の移動量を指定 u = 3.0 # ラベル用の文字列を作成 str_fc = 'None' if fc == None else "'" + fc + "'" # 2Dベクトルを作図 fig, ax = plt.subplots(figsize=(6, 3), facecolor='white') for i in range(n): ax.quiver(0, i, u, 0, facecolor=fc, edgecolor=ecs[i], linewidth=lw, units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, angles='xy', scale_units='xy', scale=1) # 矢印 str_ec = 'None' if ecs[i] == None else "'" + ecs[i] + "'" ax.text(0, i, s='edgecolor=' + str_ec + ' ', size=10, ha='right', va='center') # 引数ラベル ax.set_xticks(ticks=np.arange(u+1)) ax.set_yticks(ticks=np.arange(n)) ax.set_xlim(-6, np.ceil(u)+1) ax.set_ylim(-1, n) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('facecolor='+str_fc+', linewidth='+str(lw), loc='left', fontsize=10) fig.suptitle('pyplot.quiver(edgecolor)', fontsize=15) ax.grid(axis='x') ax.set_aspect('equal') plt.show()
「facecolor引数」のときと同様にして作図します。
linewidth引数
linewidth
引数で矢の枠線の太さを設定できます。
引数の値を変更した矢印を並べて描画します。
・作図コード(クリックで展開)
# 矢印の数を指定 n = 21 # 枠線幅の範囲を指定 lws = np.linspace(start=0, stop=10, num=n) # 面色・枠色を指定 fc = 'lightgreen' ec = 'orange' # x軸方向の移動量を指定 u = 3.0 # 座標・移動量を作成 os = np.repeat(0, repeats=n) ys = np.arange(n) us = np.repeat(u, repeats=n) # ラベル用の文字列を作成 str_fc = 'None' if fc == None else "'" + fc + "'" str_ec = 'None' if ec == None else "'" + ec + "'" # 2Dベクトルを作図 fig, ax = plt.subplots(figsize=(6, 8), facecolor='white') ax.quiver(os, ys, us, os, facecolor=fc, edgecolor=ec, linewidth=lws, units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, angles='xy', scale_units='xy', scale=1) # 矢印 for i in range(n): ax.text(0, i, s='linewidth='+str(lws[i])+' ', size=10, ha='right', va='center') # 引数ラベル ax.set_xticks(ticks=np.arange(u+1)) ax.set_yticks(ticks=np.arange(n)) ax.set_xlim(-6, np.ceil(u)+1) ax.set_ylim(-1, n) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('facecolor='+str_fc+', edgecolor='+str_ec, loc='left', fontsize=10) fig.suptitle('pyplot.quiver(linewidth)', fontsize=15) ax.grid(axis='x') ax.set_aspect('equal') plt.show()
linewidth
または省略形の lw
引数は、矢の枠線の幅です。
負の値を指定した場合は絶対値になるようです(?)。
引数の値を変更した矢印のアニメーションを作成します。
・作図コード(クリックで展開)
# フレーム数を指定 n = 101 # 枠線幅の範囲を指定 lws = np.linspace(start=0, stop=5, num=n) # 面色・枠色を指定 fc = 'lightgreen' ec = 'orange' # x軸方向の移動量を指定 u = 3.0 # ラベル用の文字列を作成 str_fc = 'None' if fc == None else "'" + fc + "'" str_ec = 'None' if ec == None else "'" + ec + "'" # グラフオブジェクトを初期化 fig, ax = plt.subplots(figsize=(6, 3), facecolor='white') fig.suptitle('pyplot.quiver(linewidth)', fontsize=15) # 作図処理を関数として定義 def update(i): # 前フレームのグラフを初期化 plt.cla() # 2Dベクトルを作図 ax.quiver(0, 0, u, 0, facecolor=fc, edgecolor=ec, linewidth=lws[i], units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, angles='xy', scale_units='xy', scale=1) # 矢印 ax.text(0, 0, s='linewidth={:.1f}'.format(lws[i])+' ', size=10, ha='right', va='center') # 引数ラベル ax.set_xticks(ticks=np.arange(u+1)) ax.set_yticks(ticks=[0]) ax.set_xlim(-3, np.ceil(u)+1) ax.set_ylim(-1, 1) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('facecolor='+str_fc+', edgecolor='+str_ec, loc='left', fontsize=10) ax.grid(axis='x') ax.set_aspect('equal') # gif画像を作成 ani = FuncAnimation(fig=fig, func=update, frames=n, interval=100) # gif画像を保存 ani.save(filename='2d_quiver_lw.gif')
点線の矢印の作図
最後は、矢全体の形状を調整して点線などの矢印を描画します。
「矢印の作図」のときと同様にして作図します。
# 座標・移動量を指定 x, y = 0.0, 1.0 u, v = 2.5, 1.5 # 矢幅・矢頭幅・矢頭長・矢軸長を指定 w = 2.0 hw = 10.0 hl = 10.0 hal = 1.5 # 枠色・面色・枠線幅を指定 fc = 'white' ec = 'orange' lw = 2.0 # ラベル用の文字列を作成 str_fc = 'None' if fc == None else "'" + fc + "'" str_ec = 'None' if ec == None else "'" + ec + "'" # 2Dベクトルを作図 fig, ax = plt.subplots(figsize=(6, 5), facecolor='white') ax.quiver(x, y, u, v, facecolor=fc, edgecolor=ec, linewidth=lw, linestyle=':', units='dots', width=w, headwidth=hw, headlength=hl, headaxislength=hal, angles='xy', scale_units='xy', scale=1, label='({: .2f}, {: .2f}, {: .2f}, {: .2f})'.format(x, y, u, v)) # 矢印 ax.set_xticks(ticks=np.arange(np.floor(x-abs(u))-1, np.ceil(x+abs(u))+2)) ax.set_yticks(ticks=np.arange(np.floor(y-abs(v))-1, np.ceil(y+abs(v))+2)) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('width={}, headwidth={}, headlength={}, headaxislength={}'.format(w, hw, hl, hal) + '\n' + 'facecolor='+str_fc+', edgecolor='+str_ec+', linewidth='+str(lw), loc='left', fontsize=10) fig.suptitle('pyplot.quiver(X, Y, U, V)', fontsize=15) ax.grid() ax.legend() ax.set_aspect('equal') plt.show()
矢の形状を上手いこと調整すると点線や破線の矢印を描画できます。(各辺が二重になっているので上手く点が重ならないと意図通りになりません。)
この記事では、矢印の色に関する引数を確認しました。ここまでは、2次元プロットを扱いました。次からは、3次元プロットを扱います。
参考リンク
- matplotlib.axes.Axes.quiver — Matplotlib 3.7.2 documentation
- Choosing Colormaps in Matplotlib — Matplotlib 3.7.2 documentation
- List of named colors — Matplotlib 3.7.2 documentation
おわりに
前回のおまけで書きました。書くつもりはなかったのですが、width引数とlinewidth引数の違いが分かからず間違って使ってたのと、グラデーションの周りの引数が分かりにくかった(vminとvmaxじゃなかった)ので、一緒に書いとくかとなりました。
【次の内容】