Python의 matplotlib에서 주석(Annotation)을 한글로 표기하기

matplotlib는 강력한 그래프 출력을 위한 라이브러리이고, 다양한 환경과 언어에서 지원됩니다. 그래프는 어떤 정보를 전달하기 위한 목적을 가지므로, 전달하고자 하는 내용을 효과적으로 표기할 수 있어야 하는데요. matplotlib에서는 텍스트나 화살표와 같은 지시선 등을 그래프 상에 표기할 수 있습니다.

아래의 코드는 그래프 위에 일반적인 텍스트와 지시선을 표기하는 파이썬의 코드입니다.

import matplotlib.pyplot as plt

plt.tight_layout()
plt.axis([0,100,0,100])
plt.plot(20, 20, "bs")
plt.plot(50, 50, "bs")
plt.plot(80, 80, "bs")


plt.annotate('중앙값', xy=(50, 50), xytext=(50,20),
            fontsize=14, ha='center',
            arrowprops=dict(facecolor='black', width=1, shrink=0.1, headwidth=10))

plt.text(25, 80, '상자 속에 글자', fontsize=24, bbox=dict(boxstyle='square', color='lightgray'))

plt.show()

결과는 다음과 같습니다.

파이썬에서 matplotlib에서 사용하는 기본 폰트가 영문이므로, 아래처럼 원하는 한글 폰트를 직접 지정하여 한글을 표기할 수 있습니다. 아래의 코드는 그래프를 출력하기 이전인 위의 코드에서 2번줄에 추가하면 됩니다.

from matplotlib import font_manager

font_fname = 'C:/Users/Dip2K/AppData/Local/Microsoft/Windows/Fonts/XOU_XWA.ttf'
font_family = font_manager.FontProperties(fname=font_fname).get_name()
print(font_family)
plt.rcParams["font.family"] = font_family

k-Means 알고리즘을 이용한 군집화(Cluster)

다음과 같은 데이터가 존재한다고 합시다.

위의 데이터는 아래의 코드로 생성된 것입니다.

import sklearn
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs

blob_centers = np.array(
    [[ 0.5,  0.5 ],
     [ 1.5,  0.5 ],
     [ 0.5,  1.5],
     [ 1.5,  1.5]])
blob_std = np.array([0.4, 0.3, 0.1, 0.1])

X, y = make_blobs(n_samples=2000, centers=blob_centers, cluster_std=blob_std, random_state=3224)

def plot_data(X, y):
    plt.scatter(X[:, 0], X[:, 1], c=y, marker='.', s=10)

plot_data(X, y)
plt.show()

위의 데이터는 4개로 구룹지을 수 있다는 것을 코드를 통해 알 수 있습니다. 이제 이 데이터를 k-Means를 이용하여 4개로 군집화하는 코드는 살펴보면 다음과 같습니다.

k = 4
kmeans = KMeans(n_clusters=k)
y_pred = kmeans.fit_predict(X)

위의 코드를 통해 kmeans 모델은 새로운 샘플 데이터에 대해서 4개의 그룹중 어떤 그룹에 포함되는지 예측할 수 있습니다. 이에 대한 시각화 코드는 다음과 같습니다.

def plot_decision_boundaries(clusterer, X, y, resolution=500):
    mins = X.min(axis=0) - 0.1
    maxs = X.max(axis=0) + 0.1
    xx, yy = np.meshgrid(np.linspace(mins[0], maxs[0], resolution), np.linspace(mins[1], maxs[1], resolution))
    Z = clusterer.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)

    plt.contourf(Z, extent=(mins[0], maxs[0], mins[1], maxs[1]), cmap="gist_stern")
    plt.contour(Z, extent=(mins[0], maxs[0], mins[1], maxs[1]), linewidths=1, colors='k')
    plot_data(X, y)

plot_decision_boundaries(kmeans, X, y)
plt.show()

위 코드의 결과는 다음과 같습니다.

실제 k-means를 적용할 시에는 군집화할 개수를 알 수 없는 경우가 대부분입니다. 위의 코드에서는 k 값인데요. 이 값을 효과적으로 결정하기 위해서는 실루엣 다이어그램(Silhouette Diagram)을 통해 효과적으로 파악할 수 있습니다.