Skip to content
주제
Matplotlib
Matplotlib 범례를 플롯 밖으로: bbox_to_anchor 치트시트

Matplotlib 범례를 플롯 밖으로: bbox_to_anchor 치트시트

게시일

업데이트

bbox_to_anchor와 loc으로 Matplotlib legend(범례)를 axes 밖 오른쪽·왼쪽·아래에 배치하세요. 필요 시 axes를 줄이고, bbox_inches='tight'로 저장해 잘림을 막습니다.

기본 범례(legend)는 axes 안에 자리 잡아 데이터를 가리는 경우가 많습니다. 바깥에 두려면 loc(범례 상자 중 어느 모서리를 앵커로 쓸지)과 bbox_to_anchor(그 앵커를 axes 좌표 어디에 둘지)를 함께 씁니다.

빠른 해결

import matplotlib.pyplot as plt
import numpy as np
 
x = np.linspace(0, 10, 200)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), label="sin(x)")
ax.plot(x, np.cos(x), label="cos(x)")
 
# Outside, upper-right of the axes
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left", borderaxespad=0)
 
plt.tight_layout()
plt.show()
배치대표 호출
axes 오른쪽legend(bbox_to_anchor=(1.02, 1), loc="upper left")
오른쪽, 세로 중앙legend(loc="center left", bbox_to_anchor=(1.02, 0.5))
아래, 가로 배치legend(loc="upper center", bbox_to_anchor=(0.5, -0.12), ncol=n)
legend(loc="lower center", bbox_to_anchor=(0.5, 1.02), ncol=n)
잘림 없이 내보내기savefig(..., bbox_inches="tight") 또는 tight_layout() / constrained_layout=True

Axes 좌표: (0, 0)은 axes 왼쪽 아래, (1, 1)은 오른쪽 위입니다. 1보다 조금 크거나 0보다 조금 작은 값은 플롯 프레임 바로 밖에 놓입니다.

문제: 데이터가 범례에 가림

fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, np.sin(x), label="sin(x)", lw=2)
ax.plot(x, np.cos(x), label="cos(x)", lw=2)
ax.legend(loc="best")  # still inside the axes
ax.set_title("Default legend (often overlaps data)")
plt.show()

Default Matplotlib legend inside the axes

loc="best"안쪽에서 덜 나쁜 모서리만 고릅니다. 범례를 figure 여백으로 보내지는 않습니다.

bbox_to_anchor + loc이 함께 동작하는 방식

  1. bbox_to_anchor=(x, y) — 기본으로 axes fraction 좌표의 점.
  2. loc="upper left" (등) — 범례 상자에서 그 앵커에 고정할 지점.
  3. borderaxespad — axes와 범례 사이 패딩. 바깥에 딱 붙이려면 0.

머릿속 모델: 플롯 위의 앵커 점 + 그 점에 앉는 범례 모서리.

범례를 오른쪽으로

fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, np.sin(x), label="sin(x)", lw=2)
ax.plot(x, np.cos(x), label="cos(x)", lw=2)
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left", borderaxespad=0)
ax.set_title("Legend outside: upper right of axes")
fig.tight_layout()
plt.show()

Legend placed outside to the right of the axes

창에서 여전히 잘리면 tight_layout() / subplotsconstrained_layout=True, 또는 다음 절처럼 axes를 줄여 공간을 확보하세요.

axes를 줄인 뒤 범례를 도킹

시리즈가 많을 때는 플롯에 전용 범례 열을 남겨 두세요.

x = np.arange(10)
fig = plt.figure(figsize=(7.2, 4.2))
ax = fig.add_subplot(111)
 
for i in range(5):
    ax.plot(x, i * x, label=f"y = {i}x", lw=2)
 
# Leave ~22% of the figure width for the legend
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.78, box.height])
ax.legend(loc="center left", bbox_to_anchor=(1.02, 0.5), borderaxespad=0)
ax.set_title("Shrink axes, legend to the right")
plt.show()

Axes shrunk with legend docked on the right

현대적인 대안: 바깥 artist와 더 잘 맞는 레이아웃 엔진으로 figure를 만듭니다.

fig, ax = plt.subplots(layout="constrained")
# ... plot ...
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left")

플롯 아래 가로 범례

ncol로 항목을 차트 아래 한 줄에 배치합니다. 슬라이드·넓은 대시보드에 적합합니다.

x = np.arange(10)
fig = plt.figure(figsize=(7.2, 4.4))
ax = fig.add_subplot(111)
 
for i in range(5):
    ax.plot(x, i * x, label=f"y = {i}x", lw=2)
 
box = ax.get_position()
ax.set_position([box.x0, box.y0 + box.height * 0.12, box.width, box.height * 0.88])
ax.legend(loc="upper center", bbox_to_anchor=(0.5, -0.12), ncol=5)
ax.set_title("Horizontal legend below the plot")
plt.show()

Horizontal legend placed below the plot

결정 가이드

상황선호
시리즈 2–4개, 단순 선 차트bbox_to_anchor=(1.02, 1), loc="upper left" + tight_layout()
시리즈 많음, 안정 레이아웃 필요axes 축소 / layout="constrained" + 오른쪽 범례
넓은 figure / 발표ncol 있는 하단 범례
어떤 상자도 방해되는 맵·이미지반투명 안쪽 범례: framealpha=0.3 (타협)
논문용 PNG/PDF 저장항상 bbox_inches="tight" 테스트 (아래)

내보내기 함정: 파일에서 바깥 범례가 사라짐

대화형 창에는 보이는데 savefig가 잘라내는 경우가 있습니다. 흔한 해결:

fig, ax = plt.subplots(figsize=(7, 4))
ax.plot(x, np.sin(x), label="sin(x)", lw=2)
ax.plot(x, np.cos(x), label="cos(x)", lw=2)
ax.legend(bbox_to_anchor=(1.02, 1), loc="upper left", borderaxespad=0)
ax.set_title("Outside legend kept with bbox_inches='tight'")
 
fig.savefig("legend-outside.png", dpi=150, bbox_inches="tight", facecolor="white")

Saved figure that keeps the outside legend via bbox_inches tight

관련 심화: savefig cuts off labels. 라벨이 여전히 겹치면 앵커를 미세 조정하기 전에 figure size를 키우세요.

상자를 옮기지 않는 추가 제어

ax.legend(
    bbox_to_anchor=(1.02, 1),
    loc="upper left",
    borderaxespad=0,
    frameon=True,
    fancybox=False,
    framealpha=0.95,
    fontsize=9,          # or prop={"size": 9}
    title="Series",
    alignment="left",
)
  • ncol — 다중 열 범례
  • framealpha — 데이터 위에 둘 수밖에 없을 때 투명도
  • title — 다중 시리즈 그룹 라벨

위치만이 아닌 일반 범례 스타일은 Matplotlib legend를 보세요.

흔한 함정

함정보이는 증상해결
loc="right"만 설정범례가 여전히 안쪽1.0 너머 bbox_to_anchor 필요
GUI에는 바깥 범례, PNG에는 없음잘린 내보내기bbox_inches="tight" 또는 constrained layout
실수로 data 좌표 bbox_to_anchor범례가 멀리 날아감기본은 axes 좌표; 의도 없으면 2-tuple, 임의 Bbox 금지
범례 글꼴이 너무 큼figure를 잠식fontsize=8–10 또는 열 수 줄이기
colorbar와 겹침여백이 찌그러짐둘 다 공간 확보, 또는 범례를 아래로

FAQ

마무리

바깥 범례는 미스터리 API가 아니라 레이아웃 문제입니다. loc으로 범례 모서리를 고정하고, bbox_to_anchor로 axes 바로 밖(> 1 또는 < 0)에 그 핀을 두고, 내보내기 때 tight/constrained로 여백이 파일에 남게 하세요. 시리즈가 많으면 오른쪽 스택, 넓은 figure면 하단 ncol 행이 잘 맞습니다.

관련 가이드