【python】矢印を複数プロットしたい。【matplotlib.pyplot.quiver】

 統計を勉強していたら、モーメントの話が出てきて、グラフに矢印をプロットしたくなった。リストで位置や長さを指定してまとめてプロットしたいなと思ったところ、quiverを使えばいいらしい、ということが分かったので、備忘録としてまとる。

plt.quiver(X,Y,U,V,units='xy',scale=1

 とりあえずこれで何とかなる。始点(X,Y)から終点(X+U, Y+V)に矢印が引かれる。で、便利なことに、すべてリストで指定できる。

import matplotlib.pyplot as plt

X = [1,2,4] #始点のX
Y = [1,1,2] #始点のY
U = [-1,2,3] #差分のX
V = [-1,2,2] #差分のY

plt.quiver(X,Y,U,V,units='xy',scale=1)
plt.show()

f:id:Chemstat:20200815072306p:plain

 とまあこんな感じにプロットすることが出来る。unitsやscaleで単位長さを設定しているのだが、結構ややこしいし、自分の用途ではあまり使わないので必要になったときに追記したいと思う。

 

plt.quiver(X,Y,U,V,units='xy',scale=1, color=["Red", "Blue", "Green"])

f:id:Chemstat:20200815075056p:plain

colorはリストで設定できる。それぞれの矢印で色を変えれるので便利。

 

矢印全体の太さ

plt.quiver(1, 0, 0, 1, units='xy', scale=1, width=0.05)
plt.quiver(2, 0, 0, 2, units='xy', scale=1, width=0.1)
plt.quiver(3, 0, 0, 3, units='xy', scale=1, width=0.2)

f:id:Chemstat:20200815075816p:plain
widthで太さも変更できる。(本当はlinewidthsでリストを指定し、個別に設定できるらしい。なぜか自分の環境では変わらなかった。要調査。)

 

矢印先端の太さ

plt.quiver(1,0,0,1, units='xy',scale=1, headaxislength=5,headlength=5,headwidth=5)
plt.quiver(2,0,0,2, units='xy',scale=1, headaxislength=10,headlength=10,headwidth=10)
plt.quiver(3,0,0,3, units='xy',scale=1, headaxislength=20,headlength=20,headwidth=20)

 

 f:id:Chemstat:20200815082349p:plain

 矢印先端部分の太さ、長さ、サイズも変更できるので、必要に応じてどうぞ。

補足

 plt.subplots_adjustやplt.tight_layoutでグラフの余白をいじったりしていると矢印の位置がずれるという問題が発生した。これは一つ目と同じプロットでX軸を伸ばしたものだ。始点は同じなのだが、矢印の終点がX軸方向に伸びず、中途半端な位置になっている。どうもx軸とy軸の単位長さが1:1に対応していないとずれちゃうようだ。

f:id:Chemstat:20200815082556p:plain

 矢印(ベクトル)の長さがx軸やy軸の長さに紐づいているせいなんじゃないかと疑っているのだが、いい解決方法が見つからずとりあえず余白の位置とかをコツコツ強引に調整している。同じように困っている人がいるかもしれないので、今回のグラフに使ったものを載せておく。なんかいい解説とかあったら教えてほしい。

%matplotlib notebook
import matplotlib.pyplot as plt

X = [1,2,4] #始点のX
Y = [1,1,2] #始点のY
U = [-1,2,3] #終点のX
V = [-1,2,2] #終点のY

fig = plt.figure(figsize=(8/2, 5/2))
ax1 =fig.add_subplot(111)
ax1.grid(axis='x', color='black', lw=0.5)
ax1.grid(axis='y', color='black', lw=0.5)
ax1.set_xlim(0,8)
ax1.set_ylim(0,5)
ax1.set( ylabel='Y', xlabel='X')
ax1.set_xticks(np.arange(0, 8.1,1))
ax1.set_yticks(np.arange(0, 5.1,1))

plt.quiver(X,Y,U,V,units='xy',scale=1, color=["Red", "Blue", "Green"])
plt.subplots_adjust(left=0.1, right=0.7, bottom=0.3, top=0.9)

plt.show()
 

参考

matplotlib.pyplot.quiver https://matplotlib.org/3.3.0/api/_as_gen/matplotlib.pyplot.quiver.html