HOWTO · Matplotlib
Matplotlib에서 가로선과 세로선을 그리는 방법
이 튜토리얼에서는 axhline과 axvline, hlines와 vlines, 그리고 axhspan과 axvspan 음영 함수를 사용해 Matplotlib에서 가로선과 세로선을 그리는 방법을 소개합니다.
이 페이지의 내용
Matplotlib에서 가로 및 세로 기준선을 그리려면, 선이 축 범위의 비율만큼 뻗어야 할 때는 axhline과 axvline을 선택하고, 양쪽 끝점을 데이터 값으로 고정해야 할 때는 hlines와 vlines를 선택하세요. 단일 값이 아니라 전체 구간을 강조하는 것이 목표라면, axhspan과 axvspan이 두 위치 사이의 영역을 음영으로 채웁니다. 각 예제는 그림을 임시 PNG 파일로 저장하고, 생성한 객체의 좌표를 출력하므로 Matplotlib가 선이나 구간을 정확히 어디에 배치했는지 확인할 수 있습니다.
Matplotlib에서 가로선과 세로선을 그리는 axhline과 axvline
axhline으로 가로선 그리기
axhline(y=...)은 데이터 좌표의 y 위치에 가로선을 배치합니다. xmin과 xmax 인수는 왼쪽과 오른쪽 끝을 축 너비의 비율로 설정하며, 보통 0부터 1 사이의 값을 사용합니다. 이는 x 데이터 값이 아닙니다. 예를 들어 xmin=0.1과 xmax=0.9는 양쪽 끝에 축 너비의 10%에 해당하는 여백을 남깁니다.
import tempfile
from pathlib import Path
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([0, 2, 4], [1, 3, 2], marker="o")
line = ax.axhline(y=2, xmin=0.1, xmax=0.9, color="tab:red")
ax.set(xlim=(0, 4), ylim=(0, 4), xlabel="x", ylabel="y")
ax.grid(True)
print("x extent (axes fraction):", line.get_xdata())
print("y position (data):", line.get_ydata())
with tempfile.TemporaryDirectory() as directory:
fig.savefig(Path(directory) / "plot.png")
plt.close(fig)
출력:
x extent (axes fraction): [0.1, 0.9]
y position (data): [2, 2]
출력된 값은 이 분담을 확인해 줍니다. 위치는 데이터 값 2이고, 범위는 축 비율 0.1과 0.9로 저장됩니다.
선은 데이터 값 y=2에 그대로 유지됩니다. x 제한을 변경해도 양쪽 끝은 여전히 축 너비의 10%에서 90%까지 뻗으므로, 선분은 표시되는 범위에 맞춰 조정됩니다.
axvline으로 세로선 그리기
axvline(x=...)은 데이터 좌표의 x 위치에 세로선을 배치합니다. ymin과 ymax 인수는 아래쪽과 위쪽 끝을 축 높이의 비율로 설정하며, 보통 0부터 1 사이의 값을 사용합니다. 예를 들어 ymin=0.1과 ymax=0.9는 양쪽 끝에 축 높이의 10%에 해당하는 여백을 남깁니다.
import tempfile
from pathlib import Path
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([0, 2, 4], [1, 3, 2], marker="o")
line = ax.axvline(x=2, ymin=0.1, ymax=0.9, color="tab:green")
ax.set(xlim=(0, 4), ylim=(0, 4), xlabel="x", ylabel="y")
ax.grid(True)
print("x position (data):", line.get_xdata())
print("y extent (axes fraction):", line.get_ydata())
with tempfile.TemporaryDirectory() as directory:
fig.savefig(Path(directory) / "plot.png")
plt.close(fig)
출력:
x position (data): [2, 2]
y extent (axes fraction): [0.1, 0.9]
여기서는 저장되는 값이 대칭으로 바뀝니다. 위치는 데이터 값 2이고, 범위는 축 비율 쌍입니다.
선은 데이터 값 x=2에 그대로 유지됩니다. y 제한을 변경해도 양쪽 끝은 여전히 축 높이의 10%에서 90%까지 뻗습니다. 이처럼 각 ax*line 함수는 데이터 좌표의 위치와 축 비율로 측정되는 범위를 결합합니다.
Matplotlib에서 가로선과 세로선을 그리는 hlines와 vlines
선의 위치와 양쪽 끝점 모두에 데이터 좌표를 사용해야 할 때는 hlines와 vlines를 사용하세요. hlines에서는 y가 높이를 제공하고 xmin과 xmax가 끝점의 x 값을 제공합니다. vlines에서는 x가 위치를 제공하고 ymin과 ymax가 끝점의 y 값을 제공합니다. 플롯 제한을 변경하면 어떤 부분이 보이는지가 달라지지만, 데이터 좌표에서의 선 위치와 끝점은 고정된 상태로 유지됩니다. 두 함수 모두 LineCollection을 반환하고 일반적인 스타일 인수를 받으므로, 이 예제는 대시 및 점선 스타일도 설정하고 label 인수를 통해 범례를 추가합니다.
import tempfile
from pathlib import Path
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([0, 2, 4], [1, 3, 2], marker="o")
horizontal = ax.hlines(y=2, xmin=1, xmax=3, color="tab:red", linestyles="--",
linewidth=2, label="horizontal segment")
vertical = ax.vlines(x=2, ymin=1, ymax=3, color="tab:green", linestyles=":",
linewidth=2, label="vertical segment")
ax.set(xlim=(0, 4), ylim=(0, 4), xlabel="x", ylabel="y")
ax.grid(True)
ax.legend(loc="upper left")
print("horizontal segment endpoints:", horizontal.get_segments()[0].tolist())
print("vertical segment endpoints:", vertical.get_segments()[0].tolist())
with tempfile.TemporaryDirectory() as directory:
fig.savefig(Path(directory) / "plot.png")
plt.close(fig)
출력:
horizontal segment endpoints: [[1.0, 2.0], [3.0, 2.0]]
vertical segment endpoints: [[2.0, 1.0], [2.0, 3.0]]
출력된 끝점은 순수한 데이터 좌표입니다. 가로 선분은 (1, 2)에서 (3, 2)까지, 세로 선분은 (2, 1)에서 (2, 3)까지 이어집니다.
네 끝점 모두가 데이터 좌표를 사용하므로, 확대하거나 제한을 변경하면 끝점이 축 비율에 맞춰 조정되는 것이 아니라 각 선분에서 보이는 부분이 달라집니다.
axhspan과 axvspan으로 Matplotlib에서 영역 음영 처리하기
선 하나만으로는 부족할 때는 대신 두 값 사이의 영역을 음영으로 채우세요. axhspan(ymin, ymax)은 두 y 데이터 값 사이의 가로 구간을 축 너비 전체에 걸쳐 채우고, axvspan(xmin, xmax)은 두 x 데이터 값 사이의 세로 구간을 높이 전체에 걸쳐 채웁니다. 데이터 뒤에 허용 범위, 목표 영역 또는 관심 기간을 표시하는 데 사용하세요. 두 함수 모두 Rectangle 패치를 반환합니다.
import tempfile
from pathlib import Path
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([0, 2, 4], [1, 3, 2], marker="o")
band_y = ax.axhspan(ymin=1.5, ymax=2.5, color="tab:orange", alpha=0.3,
label="y between 1.5 and 2.5")
band_x = ax.axvspan(xmin=1.5, xmax=2.5, color="tab:blue", alpha=0.15,
label="x between 1.5 and 2.5")
ax.set(xlim=(0, 4), ylim=(0, 4), xlabel="x", ylabel="y")
ax.grid(True)
ax.legend(loc="upper left")
print("horizontal band y range:", band_y.get_y(), "to", band_y.get_y() + band_y.get_height())
print("vertical band x range:", band_x.get_x(), "to", band_x.get_x() + band_x.get_width())
with tempfile.TemporaryDirectory() as directory:
fig.savefig(Path(directory) / "plot.png")
plt.close(fig)
출력:
horizontal band y range: 1.5 to 2.5
vertical band x range: 1.5 to 2.5
구간의 경계는 항상 데이터 좌표를 사용합니다. axhline과 마찬가지로 span 함수도 교차 방향에 대해서는 비율 인수를 받습니다. axhspan은 구간의 너비를 제한하기 위해 xmin과 xmax를 축 비율로 받고, axvspan은 ymin과 ymax를 받지만, 이렇게 그린 구간도 시작과 끝은 데이터 값입니다.
Matplotlib에서 가로선이나 세로선이 나타나지 않는 이유
두 가지 점검으로 거의 모든 ‘선이 사라졌다’는 보고를 설명할 수 있습니다. 첫 번째는 타입 오류입니다. axhline과 axvline의 비율 인수는 반드시 숫자여야 합니다. 값이 폼, CSV 파일 또는 구성 항목에서 온 경우에 흔히 발생하는 사고처럼 이들을 문자열로 전달하면, 아무것도 그려지기 전에 ValueError가 발생합니다.
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([0, 2, 4], [1, 3, 2], marker="o")
ax.axhline(y=2, xmin="0.1", xmax="0.9", color="tab:red")
plt.close(fig)
출력:
ValueError: xmin must be a single scalar value, but got 0.1
먼저 float(...) 등을 사용해 값을 숫자로 변환하면 같은 호출이 성공합니다. 이 글의 첫 번째 예제가 바로 숫자 비율을 사용한 그 호출입니다.
두 번째 점검은 표시 범위입니다. 선은 그 위치가 현재 축 제한 밖에 있더라도 데이터 좌표로 생성되므로, 그림 안에는 존재하지만 화면에서는 잘려 나갑니다.
import tempfile
from pathlib import Path
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot([0, 2, 4], [1, 3, 2], marker="o")
line = ax.axhline(y=20, color="tab:red")
ax.set(xlim=(0, 4), ylim=(0, 4), xlabel="x", ylabel="y")
ax.grid(True)
print("line y position:", line.get_ydata())
print("axes y limits:", tuple(float(v) for v in ax.get_ylim()))
with tempfile.TemporaryDirectory() as directory:
fig.savefig(Path(directory) / "plot.png")
plt.close(fig)
출력:
line y position: [20, 20]
axes y limits: (0.0, 4.0)
선은 y=20에 있는데 축은 4.0에서 멈춥니다. 위치를 포함하도록 제한을 확장하거나, 20이 실수였다면 값을 수정하면 선이 나타납니다. 같은 점검이 hlines와 vlines의 끝점, 그리고 제한 밖에 떨어진 span 경계에도 적용됩니다.
Matplotlib에서 가로선과 세로선 그리기에 대한 결론
위치는 데이터 값이되 선의 범위는 축 비율을 따라야 할 때는 axhline이나 axvline을 선택하세요. 위치와 양쪽 끝점이 데이터 값으로 유지되어야 할 때는 hlines나 vlines를 선택하고, 단일 선 대신 두 값 사이의 전체 구간을 강조해야 할 때는 axhspan이나 axvspan을 사용하세요. 이 좌표 선택은 플롯 제한을 변경한 뒤 선이 얼마나 보이는지를 결정합니다. 그리고 저장된 좌표와 축 제한을 비교하면 보이지 않는 선의 이유를 설명할 수 있습니다.