평균만 보면 데이터가 어떻게 퍼져 있는지 알 수 없다.
분포를 보려면 최소한 중앙값, 사분위수, 이상치, 쏠림 정도를 같이 봐야 하고, 이때 가장 많이 쓰는 그래프가 boxplot과 violinplot이다. 둘 다 분포를 보는 그래프지만, boxplot은 요약 통계에 강하고, violinplot은 분포 모양 자체를 보여주는 데 강하다.
즉 빠르게 정리하면 이렇다.
- boxplot: 중앙값, 사분위수, 이상치 확인용
- violinplot: 값이 어디에 몰려 있는지, 분포가 어떻게 생겼는지 확인용
이 차이를 이해하고 나면, 어떤 그래프를 먼저 봐야 할지 훨씬 쉬워진다.
평균만 보면 왜 부족할까
평균이 같아도 분포는 전혀 다를 수 있다.
예를 들어 어떤 데이터는 값이 고르게 퍼져 있을 수 있고, 다른 데이터는 특정 구간에 몰려 있을 수 있다. 또 이상치가 몇 개 섞여 있으면 평균은 쉽게 흔들린다.
그래서 분포를 볼 때는 보통 아래를 함께 확인한다.
- 중심이 어디에 있는지
- 값이 얼마나 퍼져 있는지
- 이상치가 있는지
- 한쪽으로 치우쳐 있는지
이걸 시각적으로 빠르게 보는 데 boxplot과 violinplot이 유용하다.
boxplot이 보여주는 것
boxplot은 데이터 분포를 요약된 통계 형태로 보여준다.
그래프 하나로 아래 정보를 바로 읽을 수 있다.
- 중앙값
- 25% 지점(Q1)
- 75% 지점(Q3)
- 사분위 범위(IQR)
- 이상치
즉 boxplot은 “데이터가 대충 어디에 모여 있고, 이상치가 있는지”를 빠르게 확인할 때 좋다.
특히 이런 상황에서 유용하다.
- 여러 그룹을 한 번에 비교할 때
- 이상치 유무를 먼저 볼 때
- 분포를 간단하게 요약해서 보고 싶을 때
한마디로 boxplot은 요약형 분포 그래프다.
violinplot이 보여주는 것
violinplot은 boxplot처럼 요약 통계만 보여주는 게 아니라, 분포의 밀도와 모양까지 함께 보여준다.
그래프가 넓어지는 부분은 값이 많이 몰려 있다는 뜻이고, 좁아지는 부분은 상대적으로 적다는 뜻이다.
즉 violinplot을 보면 이런 걸 더 잘 볼 수 있다.
- 값이 어느 구간에 많이 몰려 있는지
- 분포가 한쪽으로 치우쳐 있는지
- 중간이 비고 양쪽에 몰린 형태인지
- 여러 봉우리가 있는지
그래서 violinplot은 단순히 “범위가 넓다”보다 분포 모양 자체를 읽는 데 더 강하다.
한마디로 violinplot은 형태형 분포 그래프다.
boxplot과 violinplot 차이
둘 차이는 이렇게 보면 제일 빠르다.
구분 boxplot violinplot
| 강점 | 중앙값, 사분위수, 이상치 확인 | 분포 밀도와 모양 확인 |
| 해석 방식 | 통계 요약 중심 | 형태 해석 중심 |
| 장점 | 단순하고 비교가 쉬움 | 데이터 쏠림과 밀집 구간이 잘 보임 |
| 단점 | 분포 모양은 잘 안 보임 | 처음 보면 해석이 조금 낯설 수 있음 |
즉 데이터 분포를 볼 때 보통은 이렇게 생각하면 된다.
- 이상치와 범위를 먼저 보고 싶다 → boxplot
- 분포 모양까지 보고 싶다 → violinplot
- 둘 다 보고 싶다 → 같이 그리기
실무에선 둘 중 하나만 고르기보다, 오히려 나란히 같이 보는 경우가 많다.
같이 그리면 왜 좋은가
boxplot과 violinplot은 서로 대체 관계라기보다 보완 관계에 가깝다.
- boxplot은 요약이 빠르다
- violinplot은 분포 모양이 잘 보인다
그래서 두 그래프를 나란히 두면,
“중앙값은 비슷한데 분포 모양은 다르네”
같은 포인트를 더 쉽게 찾을 수 있다.
특히 데이터가 치우쳐 있거나, 특정 구간에 값이 몰려 있는 경우엔 boxplot만 봐서는 놓치는 정보가 violinplot에서 바로 보이기도 한다.
Seaborn에서 같이 그리는 방법
Seaborn은 data, x, y, hue, ax 중심으로 그래프를 그린다. boxplot과 violinplot을 나란히 그리고 싶다면 matplotlib.pyplot.subplots()로 판을 만들고, 각 축(ax)에 그래프를 넣으면 된다.
import matplotlib.pyplot as plt
import seaborn as sns
fig, axes = plt.subplots(nrows=1, ncols=2, sharey=True)
sns.boxplot(
data=data,
y="Total intl calls",
ax=axes[0]
)
sns.violinplot(
data=data,
y="Total intl calls",
ax=axes[1]
)
axes[0].set_title("Boxplot")
axes[1].set_title("Violinplot")
plt.tight_layout()
이 코드에서 중요한 건 세 가지다.
1. subplots()
그래프를 여러 개 놓을 판을 만든다.
2. ax
각 그래프를 어느 위치에 그릴지 지정한다.
3. sharey=True
두 그래프가 같은 y축 범위를 쓰게 해서 비교가 쉬워진다.
즉 이 구조는 단순히 예쁘게 그리기 위한 게 아니라,
같은 축 기준으로 분포를 비교하기 위해 쓰는 방식이다.
이상치는 무조건 제거 대상이 아니다
boxplot을 보면 이상치가 눈에 잘 띈다.
그런데 여기서 자주 하는 실수가 “이상치는 무조건 제거해야 한다”고 생각하는 거다.
실제로는 분석 목적에 따라 다르다.
예를 들어:
- 쇼핑몰 매출 데이터라면 이상치는 오류가 아니라 고액 구매 고객일 수 있고
- 통신 사용량 데이터라면 이상치는 헤비 유저일 수 있다
- 센서 데이터라면 진짜 오류일 가능성이 더 높을 수도 있다
즉 이상치는 제거 여부를 먼저 정하는 게 아니라,
왜 이상치처럼 보이는지 해석하는 것이 먼저다.
어떤 그래프를 먼저 볼까
실무에서는 보통 이렇게 간다.
빠르게 확인할 때
먼저 boxplot으로 범위, 중앙값, 이상치를 본다.
분포가 찝찝할 때
그다음 violinplot으로 실제 값이 어디에 몰렸는지 확인한다.
보고서나 비교 분석
둘을 나란히 그려서 요약과 모양을 같이 본다.
즉 둘 중 하나만 정답인 게 아니라,
확인하고 싶은 정보가 다르기 때문에 선택 기준이 달라진다고 보는 게 맞다.
정리
boxplot과 violinplot은 둘 다 분포를 보는 그래프지만, 보는 방식이 다르다.
boxplot은 중앙값, 사분위수, 이상치를 빠르게 확인하는 데 좋고, violinplot은 값이 어디에 몰려 있는지와 분포 모양을 읽는 데 좋다.
그래서 분포를 볼 때는 평균만 보지 말고,
최소한 요약 통계와 분포 형태를 함께 확인하는 습관이 필요하다.
이 둘을 같이 보면 데이터가 훨씬 덜 평면적으로 보인다!
