HOWTO · Matplotlib
Matplotlib에서 원을 그리는 방법
Matplotlib에서 패치 원, 원 방정식 및 산점도를 사용하여 원을 그릴 수 있습니다.
이 페이지의 내용
Matplotlib에서 데이터 좌표계의 기하학적 원을 그리려면 matplotlib.patches.Circle 패치를 만들어 Axes에 추가하면 됩니다. 원의 방정식으로 곡선을 그리거나, 간단한 원형 기호로 산점도 마커를 사용할 수도 있습니다. 중심과 반지름을 데이터 좌표로 지정해야 한다면 패치를 사용하는 방법이 대체로 가장 직접적입니다.
matplotlib.patches.Circle로 원 그리기
matplotlib.patches.Circle은 중심 (x, y)와 반지름으로 패치를 만듭니다. add_patch로 Axes에 추가하고, x축의 한 단위와 y축의 한 단위가 화면에서 같은 길이로 보이도록 종횡비를 같게 설정하세요.
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)로도 Axes에 추가할 수 있습니다. 이미 플롯이 있다면 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축의 한 단위가 y축의 한 단위보다 길게 그려집니다. 패치 자체는 데이터 좌표에서 여전히 원이지만 화면에서는 타원처럼 보입니다. 아래 예제는 첫 번째 예제와 같은 중심과 반지름을 사용하되 종횡비를 설정하는 줄만 생략한 것입니다.
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가 작아질 수 있는데, 이는 의도된 동작이며 데이터가 잘못된 것이 아닙니다.