포스트

Matplotlib 기초 (2) - 자주 그리는 그래프들: 분포와 관계

실무에서 데이터를 점검할 때 반복해서 그리는 그래프인 히스토그램, 박스플롯, 산점도, 막대 그래프를 성적 데이터로 그려보며, 각각이 무엇을 드러내고 언제 무엇을 골라야 하는지를 정리한 Matplotlib 기초 둘째 편입니다.

Matplotlib 기초 (2) - 자주 그리는 그래프들: 분포와 관계

데이터를 점검할 때 그리는 그래프는 사실 몇 종류로 정해져 있습니다. 분포를 보는 히스토그램과 박스플롯, 관계를 보는 산점도, 비교를 보는 막대 그래프입니다. 이 글은 이 네 가지를 성적 데이터로 그려보며 각각이 무엇을 드러내는지, 언제 무엇을 골라야 하는지를 정리합니다. 1편의 Figure와 Axes 구조를 전제로 합니다.

그래프는 질문에 따라 고른다

그래프 종류를 외우는 것보다, “지금 데이터에 무엇을 묻고 있는가”를 먼저 정하는 편이 낫습니다. 질문이 그래프를 정합니다.

  • 이 값은 어떻게 퍼져 있는가 → 히스토그램, 박스플롯
  • 두 값은 관계가 있는가 → 산점도
  • 범주별로 얼마나 다른가 → 막대 그래프

데이터 준비는 1편과 같습니다.

1
2
3
4
5
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv("https://blog.hoseunggg.com/assets/data/grades.csv")
scores = df["성적"].dropna()

히스토그램 — 값이 어떻게 퍼져 있는가

히스토그램은 값의 범위를 여러 구간(bin)으로 나누고, 각 구간에 몇 개가 들어가는지를 막대 높이로 보여줍니다. 평균과 사분위수 같은 숫자로는 안 보이던 분포의 모양이 드러납니다.

1
2
3
4
5
fig, ax = plt.subplots()
ax.hist(scores, bins=20, edgecolor="white")
ax.set_xlabel("성적")
ax.set_ylabel("빈도")
ax.set_title("성적 분포")

bins는 구간을 몇 개로 나눌지입니다. 너무 적으면 뭉개지고 너무 많으면 들쭉날쭉해지므로, 몇 번 바꿔보며 데이터가 잘 드러나는 값을 찾습니다. edgecolor로 막대 경계를 주면 붙어 있는 막대가 구분됩니다.

히스토그램에서 봐야 할 것은 세 가지입니다. 봉우리가 하나인가 여럿인가(여럿이면 성격이 다른 집단이 섞여 있다는 신호), 좌우로 치우쳤는가, 그리고 동떨어진 값이 있는가입니다. 성적처럼 상한이 100인 데이터는 오른쪽 끝에 몰리는 경우가 흔합니다.

박스플롯 — 분포를 요약해 비교한다

히스토그램이 분포의 모양을 통째로 보여준다면, 박스플롯은 분포를 다섯 숫자로 요약합니다. 최솟값, 1사분위수, 중앙값, 3사분위수, 최댓값입니다. 상자가 가운데 50%(1사분위수부터 3사분위수까지)이고, 상자 안의 선이 중앙값, 상자 밖 점이 이상치 후보입니다.

1
2
3
4
fig, ax = plt.subplots()
ax.boxplot(scores)
ax.set_ylabel("성적")
ax.set_title("성적 박스플롯")

박스플롯의 진짜 쓸모는 여러 집단을 나란히 비교할 때 나옵니다. 이수구분별로 성적 분포를 한 그림에서 비교해봅니다.

1
2
3
4
5
6
7
groups = ["전공필수", "전공선택", "교양"]
data = [df.loc[df["이수구분"] == g, "성적"].dropna() for g in groups]

fig, ax = plt.subplots()
ax.boxplot(data, labels=groups)
ax.set_ylabel("성적")
ax.set_title("이수구분별 성적 분포")

상자 여러 개가 나란히 놓이면 어느 집단의 중앙값이 높은지, 어느 집단이 더 넓게 퍼져 있는지가 한눈에 비교됩니다. 히스토그램은 집단이 많아지면 겹쳐서 못 보지만, 박스플롯은 상자를 나란히 세우면 되므로 비교에 강합니다.

산점도 — 두 값의 관계를 본다

산점도는 1편에서 한 번 그렸습니다. 두 값을 각각 x, y로 삼아 점을 찍고, 점들이 이루는 모양에서 관계를 읽습니다. 점이 우상향으로 몰리면 양의 관계, 우하향이면 음의 관계, 흩어져 있으면 관계가 약한 것입니다.

1
2
3
4
5
fig, ax = plt.subplots()
ax.scatter(df["학점"], df["성적"], alpha=0.3)
ax.set_xlabel("학점")
ax.set_ylabel("성적")
ax.set_title("학점과 성적의 관계")

산점도에서 주의할 점은 점이 겹치는 것입니다. 데이터가 많으면 같은 자리에 점이 수십 개 쌓여도 하나로 보여, 실제 밀도를 오해하게 됩니다. alpha로 투명도를 낮추면 겹친 곳이 진하게 나타나 밀도가 드러납니다. 점이 아주 많을 때는 산점도 대신 밀도를 색으로 표현하는 hexbin이 대안입니다.

1
2
fig, ax = plt.subplots()
ax.hexbin(df["학점"], df["성적"], gridsize=20, cmap="Blues")

막대 그래프 — 범주별로 비교한다

막대 그래프는 범주마다 하나의 값(개수, 평균, 합계)을 막대 높이로 비교합니다. pandas의 집계 결과를 그대로 그리는 경우가 대부분입니다.

1
2
3
4
5
6
7
grade_counts = df["평점"].value_counts().sort_index()

fig, ax = plt.subplots()
ax.bar(grade_counts.index, grade_counts.values)
ax.set_xlabel("평점")
ax.set_ylabel("과목 수")
ax.set_title("평점 분포")

히스토그램과 막대 그래프는 생김새가 비슷하지만 다릅니다. 히스토그램은 연속값을 구간으로 나눈 것이라 막대가 붙어 있고, 막대 그래프는 이미 나뉜 범주를 비교하는 것이라 막대가 떨어져 있습니다. 성적(연속값)은 히스토그램, 평점(A, B, C 같은 범주)은 막대 그래프입니다.

무엇을 언제 그리는가

질문그래프핵심
한 값이 어떻게 퍼졌나히스토그램봉우리, 치우침, 동떨어진 값
여러 집단의 분포 비교박스플롯상자를 나란히 세워 중앙값과 폭 비교
두 값의 관계산점도겹침은 alpha, 너무 많으면 hexbin
범주별 크기 비교막대 그래프이미 나뉜 범주. 히스토그램과 구분

데이터를 받으면 먼저 수치 컬럼은 히스토그램으로 분포를 보고, 범주 컬럼은 막대 그래프로 빈도를 보고, 관심 있는 두 값은 산점도로 관계를 봅니다. 이 세 장이 Pandas 기초 1편의 “첫 점검”을 그림으로 확장한 것입니다. 다음 글에서는 이 그래프들을 한 화면에 여러 개 배치하고 색과 축을 다듬는 법, 그리고 pandas에서 그래프를 바로 그리는 df.plot()을 다룹니다.

다음 글: Matplotlib 기초 (3) - 여러 그래프와 꾸미기, pandas 연동

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.