본문 바로가기
데이터 분석/시각화

[Matplotlib] 메인 눈금(Major Tick), 서브 눈금(Minor Tick) 라벨 따로 지정하기 (feat. MultipleLocator)

by 부자 꽁냥이 2023. 5. 18.

안녕하세요~ 꽁냥이에요. 꽁냥이가 시각화를 하다가 메인 눈금(Major Tick), 서브 눈금(Minor Tick)에 라벨을 따로 설정해야 할 일이 생겼는데 이게 꽤나 번거로운 작업이어서 이번 포스팅에 정리해보려고 합니다.


   메인 눈금(Major Tick), 서브 눈금(Minor Tick) 라벨 따로 지정

먼저 아래 코드는 A, B Class에서 5명의 수학, 역사, 컴퓨터 성적을 박스 플롯으로 그린 것입니다. 그러고 나서 A, B Class는 서브 눈금(Minor Tick) 라벨로하고 과목은 메인 눈금(Major Tick) 라벨로 설정할 것입니다. 여기서는 핵심적인 부분만 설명하기로 하고 나머지는 주석을 참고해 주세요.

 

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

from matplotlib.ticker import MultipleLocator

## 데이터 생성
a_class_math = [100, 90, 69, 80, 75]
b_class_math = [96, 93, 77, 60, 55]
a_class_history = [77, 80, 91, 84, 95]
b_class_history = [87, 100, 87, 60, 75]
a_class_computer = [88, 66, 98, 68, 100]
b_class_computer = [98, 76, 80, 76, 70]

a_class_data = [
    a_class_math, a_class_history, a_class_computer
]
b_class_data = [
    b_class_math, b_class_history, b_class_computer
]

## 시각화
fig = plt.figure(figsize=(8,8))
fig.set_facecolor('white')
ax = fig.add_subplot()

a_color = 'r'
a_positions = np.arange(3)-0.25
b_color = 'b'
b_positions = np.arange(3)+0.25

## 박스 플롯 두개 그리기
ax.boxplot(a_class_data,
           patch_artist=True, ## 박스 안쪽 여백에 색상을 입히기 위해서 반드시 True로 해줘야함
           positions=a_positions, ## 박스 포지션 x 좌표
           widths=0.25, ## 박스 폭
           flierprops=dict(markerfacecolor=a_color, markeredgecolor='none'),## 마커테두리 컬러
           medianprops=dict(color=a_color,linewidth=3), ## 중앙선 테두리 컬러
           capprops=dict(color=a_color, linewidth=3), ## 최상단, 최하단 선과 직사각형을 잇는 선 테두리 컬러
           whiskerprops=dict(color=a_color, linewidth=3), ## 세로선 컬러
           boxprops=dict(facecolor='yellow', color=a_color), ## 박스테두리와 안쪽 여백 컬러
           )

ax.boxplot(b_class_data,
           patch_artist=True, 
           positions=b_positions,
           widths=0.25,
           flierprops=dict(markerfacecolor=b_color, markeredgecolor='none'),
           medianprops=dict(color=b_color,linewidth=3), 
           capprops=dict(color=b_color, linewidth=3), 
           whiskerprops=dict(color=b_color, linewidth=3), 
           boxprops=dict(facecolor='lightgreen', color=b_color),
           )
ax.set_xticks(np.concatenate([a_positions, b_positions])) ## x축 눈금 재배열
ax.set_xlim((-0.5, 2.5)) ## x축 하한과 상한 설정

def major_formatter(x, pos):
    label = None
    if pos==2:
        label = 'Math'
    elif pos==4:
        label = 'History'
    elif pos==6:
        label = 'Computer' 
    return label

def minor_formatter(x, pos):
    if pos%2==1:
        label = 'A Class'
    else:
        label = 'B Class'
    return label

ax.xaxis.set_major_locator(MultipleLocator(0.5))
ax.xaxis.set_major_formatter(major_formatter)
ax.xaxis.set_minor_locator(MultipleLocator(0.25))
ax.xaxis.set_minor_formatter(minor_formatter)

ax.tick_params(axis='x', which='both', width=0)
ax.tick_params(axis='x', which='minor', labelsize=12)
ax.tick_params(axis='x', which='major', length=15, labelsize=15)
plt.show()

 

Line 57~72

메인 눈금과 서브 눈금에 적용할 라벨을 생성하는 함수입니다. 이 함수는 set_minor_formatter에 인자로 넣어주는 함수입니다. 이때 인자로 넣어주는 함수는 x값과 위치 인덱스를 인자로 받아야 합니다.

 

메인 눈금 라벨 함수(major_formatter)는 위치 인덱스가 2인 경우 'Math', 4인 경우 'History', 6인 경우 'Computer'를 라벨로 설정하게 됩니다. 메인 눈금 라벨(minor_formatter) 또한 마찬가지입니다.

 

Line 74~77

여기서는 메인 눈금과 서브 눈금의 위치와 라벨을 적용합니다. 메인 눈금의 위치는 set_major_locater를 이용하며 여기에 MultipleLocator 클래스를 넣어줍니다. 이때 메인 눈금 간격이 0.5이므로 MultipleLocator에 0.5를 넣어줍니다. 그리고 set_minor_formatter에 메인 눈금 라벨 함수 major_formatter을 넣어줌으로써 메인 눈금 라벨을 생성시킵니다(Line 74~75). 서브 눈금도 비슷한 원리입니다.

 

Line 79~81

이제 불필요한 눈금은 안 보이게 해 주겠습니다. tick_params에서 width=0으로 설정하여 눈금을 없애줍니다(ㅣLine 79). 그리고 메인 눈금 라벨은 서브 눈금 라벨 보다 더 아래에 위치하도록 length=15로 설정했습니다. 눈금이 길어야 더 아래로 갈 테니까요(Line 81)

 

이제 위 코드를 실행하면 아래와 같이 x축 메인 눈금 라벨과 서브 눈금 라벨이 예쁘게 적용된 것을 알 수 있습니다.


댓글


맨 위로