HOWTO · Matplotlib
Matplotlib で円をプロットする方法
Matplotlib でパッチ円、円方程式、および散布図を使用して円をプロットできます。
このページの内容
Matplotlibで幾何学的な円を描くには、matplotlib.patches.Circleを使ってパッチをAxesに追加します。円の方程式から曲線を描く方法や、簡単な円形記号として散布図マーカーを使う方法もあります。中心と半径をデータ座標で指定する場合は、通常、パッチを使うのが最も直接的です。
matplotlib.patches.Circleで円を描く
matplotlib.patches.Circleは、中心(x, y)と半径からパッチを作成します。add_patchでAxesに追加し、x軸の1単位とy軸の1単位が画面上で同じ長さになるようにアスペクト比を等しくします。
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
fig, ax = plt.subplots()
ax.add_patch(Circle((2, 1), radius=0.75, fill=False, linewidth=2))
ax.set_aspect("equal", adjustable="box")
ax.set_xlim(0, 4)
ax.set_ylim(-1, 3)
ax.set_title("Circle patch")
plt.show()
最初の引数を変えると中心を移動でき、radiusを変えると円の大きさを調整できます。fill=True(既定値)なら円の内部が塗りつぶされ、fill=Falseなら輪郭だけが描画されます。CircleはArtistなので、ax.add_artist(circle)で追加することもできます。すでにプロットがある場合は、plt.gcf().gca().add_artist(circle)を使うと現在のFigureにある現在のAxesへ追加できます。複数のプロットがあるFigureでは、Axesを明示するほうが分かりやすくなります。
軸の範囲を手動で設定する場合は、円全体が収まるようにします。中心が(cx, cy)、半径がrなら、xの範囲にはcx - rからcx + rまで、yの範囲にはcy - rからcy + rまでを含めます。この範囲の内側で軸を止めると、パッチや方程式から描いた曲線の一部が隠れます。輪郭を枠の近くでも見やすくするには、周囲に少し余白を設けてください。
方程式から円を描く
媒介変数表示では、円周上の点を表します。中心が(cx, cy)、半径がrのとき、x = cx + r cos(theta)およびy = cy + r sin(theta)を使います。角度を0から2πまでサンプリングすると、円全体の曲線をたどれます。
import numpy as np
import matplotlib.pyplot as plt
center_x, center_y = 2, 1
radius = 0.75
theta = np.linspace(0, 2 * np.pi, 200)
x = center_x + radius * np.cos(theta)
y = center_y + radius * np.sin(theta)
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_aspect("equal", adjustable="box")
ax.set_title("Circle from a parametric equation")
plt.show()
中心と半径を使う方程式(x - cx)² + (y - cy)² = r²は、レベル0の等高線として描くこともできます。左辺からr**2を引き、その値をメッシュグリッド上で計算して、0の等高線を描画します。グリッドの範囲には円全体が入るようにし、軸のスケールも等しくしてください。そうしないと、表示された円が引き伸ばされて見えることがあります。
import numpy as np
import matplotlib.pyplot as plt
center_x, center_y = 2, 1
radius = 0.75
x = np.linspace(center_x - radius - 0.25, center_x + radius + 0.25, 100)
y = np.linspace(center_y - radius - 0.25, center_y + radius + 0.25, 100)
X, Y = np.meshgrid(x, y)
values = (X - center_x) ** 2 + (Y - center_y) ** 2 - radius ** 2
fig, ax = plt.subplots()
ax.contour(X, Y, values, levels=[0])
ax.set_aspect("equal", adjustable="box")
ax.set_title("Circle from the center-radius equation")
plt.show()
散布図マーカーで円を描く
scatterは、指定した各データ点にマーカーを描きます。引数sでマーカーの面積を平方ポイント単位で指定します。そのため、データ座標で半径を測る幾何学的な円ではなく、画面上の大きさを保つ円形記号に適しています。
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.scatter([2], [1], s=500, marker="o")
ax.set_xlim(0, 4)
ax.set_ylim(-1, 3)
ax.set_aspect("equal", adjustable="box")
ax.set_title("Circular scatter marker")
plt.show()
sを増減すると、マーカーの表示面積を調整できます。半径をプロットの軸上の距離に対応させる場合はCircleパッチを使い、データ点に一定の見た目のマーカーを置きたい場合は散布図マーカーを使います。
表示サイズが一定のマーカーは、測定点の強調、中心の表示、拡大・縮小するプロットへの記号の配置などに便利です。軸のスケールを変えても、マーカーの大きさは組版上のポイントに基づくため、プロット内の一定距離を表すものではありません。円そのものがデータ値と比較する半径を表す場合は、パッチまたは方程式による曲線を選んでください。
円が楕円に見える理由
これまでの例はすべて、set_aspect("equal", adjustable="box")でアスペクト比を等しく設定しています。この行がない場合、Matplotlibは自動のアスペクト比を使います。Axesは枠いっぱいに広がり、枠は縦より横が長いため、x軸の1単位がy軸の1単位より長く描画されます。パッチ自体はデータ座標では円のままですが、画面上では楕円のように見えます。次の例は、最初に紹介した例と同じ中心と半径を使い、アスペクト比の行だけを省略したものです。
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
fig, ax = plt.subplots()
ax.add_patch(Circle((2, 1), radius=0.75, fill=False, linewidth=2))
ax.set_xlim(0, 4)
ax.set_ylim(-1, 3)
ax.set_title("Circle patch without an equal aspect ratio")
plt.show()
修正するには、これまでの例のように、範囲を設定する前にax.set_aspect("equal", adjustable="box")を追加します。方程式による曲線や等高線でも同じことが起こります。アスペクト比が等しくないと、どの方法でも表示が引き伸ばされて見えます。adjustable="box"を指定すると、両軸のスケールをそろえるためにAxesが小さくなる場合がありますが、これは想定どおりの動作であり、データの誤りではありません。