HOWTO · Matplotlib

Matplotlib 산점도에서 마커 크기 설정하기

Matplotlib 산점도에서 모든 점에 같은 마커 크기를 지정하거나 점마다 크기를 바꾸고, 마커 면적을 올바르게 조정하는 방법을 설명합니다.

이 페이지의 내용

Matplotlib 산점도에서 마커 크기를 설정하려면 Axes.scatters 인수를 사용하세요. 스칼라 값은 모든 점에 동일한 공칭 면적을 적용하고, 1차원 목록이나 배열은 각 점에 면적을 지정하므로 xy와 길이가 같아야 합니다.

s로 마커 크기 설정하기

Matplotlib 산점도에서 마커 크기를 설정하려면 Axes.scatters 인수를 전달합니다. s=80과 같은 스칼라는 모든 점에 동일한 명목 면적을 적용합니다. 1차원 리스트나 배열을 전달하면 각 점에 서로 다른 면적을 적용할 수 있지만, 값의 개수는 xy와 같아야 합니다. 예를 들어 한 가지 크기에는 ax.scatter(x, y, s=80)을 사용하고, 네 점의 크기를 각각 지정하려면 ax.scatter(x, y, s=[20, 40, 80, 160])을 사용합니다.

관측값마다 크기가 달라야 한다면 scatter를 사용합니다. 관련된 plot 메서드는 하나의 선형 마커 치수를 markersize로 지정합니다.

한 가지 크기 또는 점마다 다른 크기 지정하기

다음의 재현 가능한 예제는 스칼라 크기의 컬렉션과 데이터에서 크기를 계산한 컬렉션을 나란히 배치합니다. 같은 값을 색상에도 매핑하고, 겹친 마커를 보기 쉽게 alpha를 사용합니다. 결과를 이미지로 저장하므로 대화형 백엔드가 없어도 확인할 수 있습니다.

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [2, 3, 5, 7, 11]
values = [1, 2, 4, 7, 11]
sizes = [40 + value * 20 for value in values]

fig, (top, bottom) = plt.subplots(2, 1, figsize=(6, 7), layout="constrained")
uniform = top.scatter(x, y, s=80, color="tab:blue")
varying = bottom.scatter(x, y, s=sizes, c=values, cmap="viridis", alpha=0.75)

top.set(title="s = 80", xlabel="x", ylabel="y")
bottom.set(title="s = [60, 80, 120, 180, 260]", xlabel="x", ylabel="y")
fig.colorbar(varying, ax=bottom)

print("scalar sizes:", uniform.get_sizes().tolist())
print("per-point sizes:", varying.get_sizes().tolist())
fig.savefig("scatter-marker-sizes.webp", dpi=120)

PathCollection이 보관한 정확한 s 값은 다음과 같습니다.

scalar sizes: [80]
per-point sizes: [60, 80, 120, 180, 260]

하나의 스칼라 마커 면적과 점마다 지정한 다섯 개의 면적을 비교하는 두 Matplotlib 산점도.

이 변환은 40에서 시작하여 데이터 단위마다 20을 더합니다. 따라서 가장 작은 값도 보이면서 가장 큰 값이 축을 압도하지 않습니다. 실제 데이터에서는 극단적인 원시 값을 그대로 전달하지 말고 설명 가능한 크기 범위의 최솟값과 최댓값을 정하십시오. 색상은 같은 변수나 다른 변수를 나타낼 수 있으며, 색상이 수량을 표현한다면 컬러바를 추가합니다.

제곱 포인트와 기본값 이해하기

Matplotlib scatter 문서s의 단위를 제곱 포인트(pt²)로 정의하며, 1포인트는 1/72인치입니다. 기본값은 rcParams['lines.markersize'] ** 2입니다. 따라서 s는 명목 마커 면적에 비례하지만, s=100이 화면에서 정확히 10×10포인트인 모양을 보장하지는 않습니다. 최종 윤곽은 마커 경로, 그림 DPI, 테두리 스타일의 영향을 받습니다.

작은 마커에서는 테두리의 영향이 특히 큽니다. linewidths가 0보다 크고 edgecolors가 표시되면 선이 마커 경계 중앙에 그려져 유효 바깥 치수가 선 너비의 절반만큼 늘어납니다. 작은 채움 마커를 비교할 때 테두리가 겉보기 크기를 바꾸지 않게 하려면 linewidths=0 또는 edgecolors="none"을 사용합니다.

마커 크기는 표시 공간의 측정값이며 x축이나 y축의 데이터 단위가 아닙니다. 따라서 확대하거나 축 범위를 바꿔도 마커가 데이터 좌표의 반지름을 나타내지는 않습니다.

마커 면적과 선형 너비를 올바르게 조정하기

s를 2배로 하면 명목 면적도 2배가 됩니다. 선형 바깥 치수는 면적의 제곱근에 대략 비례하므로, 같은 모양의 마커에서 s를 4배로 하면 너비가 약 2배가 됩니다. 이는 비례 관계를 설명하는 시각적 규칙이며 모든 마커 경로에 대한 정확한 기하학적 보장은 아닙니다.

import matplotlib.pyplot as plt

base = 36
area_sizes = [base, 2 * base, 4 * base]

fig, (top, bottom) = plt.subplots(2, 1, figsize=(6, 7), layout="constrained")
top.scatter([1, 2, 3], [1, 1, 1], s=area_sizes, linewidths=0)
top.set(title="s = [36, 72, 144]", yticks=[])
top.set_xticks([1, 2, 3], ["1", "2", "4"])

bottom.scatter([1], [1], s=10**2, linewidths=0)
(line,) = bottom.plot([2], [1], marker="o", linestyle="none", markersize=10,
                     color="tab:orange")
bottom.set(title="scatter: s = 10**2    plot: markersize = 10", xlim=(0.5, 2.5), yticks=[])

print("scatter areas:", area_sizes)
print("plot markersize:", line.get_markersize())
fig.savefig("scatter-size-scaling.webp", dpi=120)

선택한 값과 Line2D 마커 치수는 다음과 같습니다.

scatter areas: [36, 72, 144]
plot markersize: 10.0

산점도 면적 배율과 scatter의 s, plot의 markersize를 비교하는 Matplotlib 출력.

scatter(s=...)plot(markersize=...) 중 선택하기

산점도, 특히 관측값마다 면적이나 색상이 달라야 할 때는 scatter(s=...)를 사용합니다. 모든 노드가 같은 마커 크기를 공유하는 Line2D를 그릴 때는 plot(marker="o", markersize=10)을 사용합니다. Matplotlib plot 문서에 따르면 markersize(또는 ms)는 포인트 단위의 선형 크기이며, scatter가 받는 제곱 포인트 면적이 아닙니다.

원형 마커에서 scatter(s=10**2)plot(markersize=10)은 서로 관련된 명목 치수를 표현하지만 픽셀 단위로 완전히 같다고 가정해서는 안 됩니다. 정규화된 경로, 테두리, 렌더링 백엔드, 래스터화가 달라 컬렉션과 선의 마커가 다르게 보일 수 있습니다.

점 개수와 맞지 않는 크기 배열 수정하기

스칼라가 아닌 s는 그리는 점의 개수와 같은 길이여야 합니다. 다음 예제는 전체 트레이스백 없이 출력할 수 있도록 현재 Matplotlib 진단을 포착합니다.

import matplotlib.pyplot as plt

x = [1, 2, 3]
y = [1, 4, 9]

try:
    plt.scatter(x, y, s=[40, 80])
except ValueError as error:
    print(f"{type(error).__name__}: {error}")
else:
    raise AssertionError("a mismatched size array should fail")

Matplotlib 3.11.2에서 출력은 다음과 같습니다.

ValueError: s (size 2) cannot be broadcast to match x and y (size 3)

이전 Matplotlib 릴리스는 ValueError 문구가 다를 수 있지만 수정 방법은 같습니다. 세 개의 (x, y) 점에는 세 개의 크기 값을 전달하거나 하나의 스칼라 크기를 전달하십시오.