matplotlib으로 여러 데이터 계열의 오류 막대(error bar)를 한 그래프에 그리면 마커와 오류 막대가 서로 겹쳐 가독성이 떨어지는 경우가 자주 있습니다. 이 문제는 Affine2D 변환을 활용해 각 데이터 계열을 x축 방향으로 살짝 이동시켜 플롯하면 간단하게 해결할 수 있습니다.
구현 단계
- 그림(figure) 크기를 설정하고 서브플롯 주변 및 사이의 패딩을 조정합니다.
- 데이터 레이블로 사용할 이름 리스트를 생성합니다.
- y1, y2 데이터 포인트와 오류 값 ye1, ye2를 준비합니다.
- figure와 서브플롯을 생성합니다.
- Affine2D를 이용해 x축 방향으로 ±0.1만큼 평행 이동하는 변환(trans1, trans2)을 만듭니다.
- errorbar() 메서드로 각 계열에 오류 막대를 그리고, transform 인자에 앞서 만든 변환을 적용합니다.
- show() 메서드로 결과 그림을 화면에 출력합니다.
전체 코드 예제
import numpy as np import matplotlib.pyplot as plt from matplotlib.transforms import Affine2D plt.rcParams["figure.figsize"] = [7.50, 3.50] plt.rcParams["figure.autolayout"] = True x = ['Jack', 'James', 'Tom', 'Garry'] y1, y2 = np.random.randn(2, len(x)) ye1, ye2 = np.random.rand(2, len(x))*4+0.3 fig, ax = plt.subplots() trans1 = Affine2D().translate(-0.1, 0.0) + ax.transData trans2 = Affine2D().translate(0.1, 0.0) + ax.transData er1 = ax.errorbar(x, y1, yerr=ye1, marker="*", linestyle="none", transform=trans1) er2 = ax.errorbar(x, y2, yerr=ye2, marker="o", linestyle="none", transform=trans2) plt.show()
핵심 원리 설명
Affine2D().translate(-0.1, 0.0)은 데이터 좌표계에서 x 방향으로 -0.1만큼, translate(0.1, 0.0)은 +0.1만큼 이동시키는 아핀 변환입니다. 이 변환에 ax.transData를 더해 최종 변환 행렬을 구성한 뒤 errorbar()의 transform 인자에 전달하면, 두 데이터 계열이 동일한 카테고리 위치에서 좌우로 벌어져 그려집니다. 그 결과 별표(*) 마커와 원(o) 마커, 그리고 각 계열의 오류 막대가 겹치지 않고 명확하게 구분됩니다.
두 계열 간격이 너무 좁거나 넓다고 느껴진다면 translate()의 x 이동 값을 조정해 원하는 간격을 찾을 수 있습니다. 데이터 계열이 세 개 이상일 때도 각각 다른 오프셋 값을 부여하면 동일한 방식으로 확장할 수 있습니다.
실행 결과
위 코드를 실행하면 다음과 같은 그래프가 출력됩니다. 두 데이터 계열의 마커와 오류 막대가 서로 겹치지 않고 나란히 배치된 것을 확인할 수 있습니다.
