Matplotlib 주석과 텍스트: 인사이트를 또렷하게
Updated on
피크나 막대에 라벨이 없으면 독자는 추측해야 합니다. 텍스트가 겹치거나 데이터와 멀어지면 메시지가 흐려집니다. 짧은 라벨, 알맞은 화살표, 일관된 폰트로 시선을 안내하면 해결됩니다.
상황별 텍스트 도구
| 작업 | 도구 | 이유 |
|---|---|---|
| 특정 지점을 화살표로 표시 | annotate | 텍스트와 화살표를 한 번에 설정 |
| 축 좌표에 자유 텍스트 | text | 제목, 패널 노트 등에 적합 |
| 막대 자동 라벨링 | bar_label | 라벨을 막대에 고정 |
| 라벨을 영역 안에 유지 | clip_on=True, 오프셋 | 텍스트가 축 밖으로 나가는 것 방지 |
| 텍스트 줄바꿈/포맷 | textwrap.fill, f-string | 짧고 읽기 쉬운 라벨 유지 |
피크를 화살표로 강조
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 300)
y = np.sin(x) * np.exp(-x / 5)
fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, y, color="tab:blue")
peak_idx = np.argmax(y)
peak_x, peak_y = x[peak_idx], y[peak_idx]
ax.annotate(
"피크",
xy=(peak_x, peak_y),
xytext=(peak_x + 1.2, peak_y + 0.2),
arrowprops=dict(arrowstyle="->", color="tab:red", lw=1.5),
bbox=dict(boxstyle="round,pad=0.3", fc="white", ec="tab:red", alpha=0.9),
fontsize=10,
color="tab:red",
)
ax.set_xlabel("Time (s)")
ax.set_ylabel("Amplitude")
ax.grid(True, linestyle="--", alpha=0.3)
plt.tight_layout()
plt.show()팁:
xytext로 약간 이동해 화살표를 짧고 읽기 쉽게 유지.bbox로 배경을 밝게 해 복잡한 플롯에서 대비 확보.- 2~4 단어로 간결하게 써서 데이터를 가리지 않는다.
막대를 겹치지 않게 라벨링
import matplotlib.pyplot as plt
items = ["A", "B", "C", "D"]
values = [28, 35, 30, 22]
fig, ax = plt.subplots(figsize=(6, 4))
bars = ax.bar(items, values, color="tab:purple", alpha=0.9)
ax.bar_label(bars, labels=[f"{v}k" for v in values], padding=3)
ax.set_ylabel("Units sold")
ax.set_ylim(0, 40)
plt.tight_layout()
plt.show()팁:
padding으로 거리를 조절; 음수면 막대 내부에 배치.- 누적 막대는
label_type="center"로 각 스택의 중앙에 배치. - 값이 작으면 텍스트 색을 흰색으로 바꾸고 내부에 배치해 대비 확보.
인라인 노트와 안전한 위치 잡기
ax.text(
0.02, 0.95, "Experiment 3\nn=120",
transform=ax.transAxes,
ha="left", va="top",
fontsize=9,
bbox=dict(boxstyle="round", fc="white", ec="0.7", alpha=0.8)
)가이드:
transform=ax.transAxes로 0–1 좌표를 사용하면 리사이즈 후에도 같은 구석에 남는다.clip_on=True로 텍스트가 영역 밖으로 나가는 것을 막는다.ha/va정렬과 짧은 줄바꿈으로 가장자리 충돌을 피한다.
문제 해결 체크
- 라벨이 겹치나? 글꼴을 줄이고
padding을 조정하거나 약간 회전. - 화살표가 가리나?
zorder를 올리거나 면적 채우기 뒤에 그린다. - 텍스트가 밖으로 나가나?
constrained_layout=True또는textwrap.fill로 줄인다.