StuDyata.zip

Python으로 하는 데이터 시각화 | 기술 통계부터 matplotlib, seaborn, plotly까지 전체 정리 본문

Codeit Sprint/공부 기록

Python으로 하는 데이터 시각화 | 기술 통계부터 matplotlib, seaborn, plotly까지 전체 정리

자유를원해 2026. 3. 30. 08:44

이 글은 코드잇 스프린트 데이터 분석가 과정 학습 기록입니다.
수업 내용과 느낀 점을 매일 정리하며 데이터 분석 공부 과정을 기록하고 있습니다.

🖥️Python 시각화 라이브러리 3가지 총정리

이번 이론은 파트 1의 마지막 파이썬 이론 강의로, 파이썬의 대표적인 시각화 라이브러리인 matplotlib, seaborn, plotly를 배워보는 시간이었다. 같은 시각화 라이브러리라고 해도 사용할 수 있는 그래프 종류나 문법, 커스터마이징 방식이 모두 달라서 정리하는 과정도 생각보다 훨씬 쉽지 않았다. 솔직히 이 정리 글도 정말 많이 미루다가,,, 이제서야 겨우 올리게 되었다...^^

 

그래도 이번 이론 강의가 끝나면 이어서 EDA 실습을 진행하고, 마지막으로는 Tableau 같은 시각화 툴도 배우게 되는 만큼, 이 과정 역시 차근차근 지나가리라 생각하며 정리해보았다. 이번 글에서는 세 라이브러리의 특징과 주요 그래프 종류, 그리고 기본적인 커스터마이징 방법까지 한 번에 정리해보려고 한다.

📊통계의 종류

통계는 어떤 현상을 종합적으로 한눈에 알아보기 쉽게 일정한 체계에 따라 숫자로 나타내는 것이다. 통계는 크게 두 가지 분야로 나뉜다.

 

📍기술 통계 (descriptive statistics)

  • 데이터를 몇 가지 요약값으로 설명하는 것.
  • 여기서의 “기술”은 테크놀로지의 기술이 아니라, 표현하고 서술한다는 의미의 기술이다.
  • 숫자를 이용하여 자료의 정보를 요약하고 기술하는 것이다.

📍추론 통계 (inferential statistics)

  • 표본을 바탕으로 모집단을 추론하는 것.
  • 강사님께서는 국을 한 수저 떠서 맛을 보는 예시로 설명하셨다. (국을 전부 먹어봐야 맛을 아는 것이 아니라, 일부를 보고 전체를 추론하는 방식이라는 점)
  • 이 부분은 나중에 Part 2에서 더 학습!

🧮대표값과 산포도

📍 대표값

대표값은 데이터 집합의 중심 경향을 나타내며, 데이터의 특성을 전체 데이터를 대표하는 하나의 값으로 요약한 것이다. 예를 들어 연봉 평균은 '모든 직원의 연봉이 이렇다'는 뜻이 아니라, 전체적인 경향이 이렇다는 의미이다.

 

대표값으로는 보통 다음을 사용한다.

  • 평균(mean)
    : 데이터를 모두 더한 뒤 데이터 개수로 나눈 값.

  • 중앙값(median)
    : 데이터를 오름차순 정렬했을 때 중앙에 위치한 값, 데이터 개수가 짝수면 가운데 두 값의 평균으로 구한다.

  • 최빈값(mode)
    : 가장 자주 등장하는 값, 하나만 존재하는 것이 아니라 여러 개가 나올 수도 있으며 범주형 데이터와 수치형 데이터 모두에 적용 가능하다.

📍 산포도

산포도는 데이터들이 얼마나 흩어져 있는지를 나타내는 변동성 지표이다.

  • 분산(variance)
    : 편차 제곱의 평균, 편차를 제곱하는 이유는 음수와 양수를 모두 양수화하면서, 큰 편차를 더 강조하기 위해서이다. 편차는 각 데이터 값과 평균의 차이이며, 편차의 합은 항상 0이다!

  • 표준편차(standard deviation)
    : 분산의 제곱근, 제곱된 단위를 다시 원래 단위로 되돌리기 위해 루트를 씌운다. 그래서! 분산보다 표준편차가 해석하기 더 쉽다. 즉, 분산/표준편차가 작으면 → 값들이 평균 근처에 몰려 있다는 것,  분산/표준편차가 크면 → 값들이 평균에서 멀리 퍼져 있다는 것.

  • 범위(range)
    : 최댓값 - 최솟값

  • 사분위범위(IQR)
    : Q3 - Q1, 75% 지점과 25% 지점의 차이이다.

💣이상치(outlier)

이상치는 데이터 집합에서 대부분의 데이터와 비교했을 때 현저하게 크거나 작은 값이다.

 

📍 이상치 발생 원인

  • 오류: 잘못 입력된 값
  • 극단값: 실제로 매우 특이한 값

📍 IQR 기반 이상치 탐지

IQR(사분위범위)을 이용하여 중앙에 모인 데이터에서 너무 멀리 벗어난 값을 이상치로 본다. 상자그림(box plot)으로 보면 하한 쪽 이상치인지, 상한 쪽 이상치인지도 한눈에 확인할 수 있다.

 

기준은,

  • IQR = Q3 - Q1
  • 하한 = Q1 - (1.5 × IQR), 상한 = Q3 + (1.5 × IQR)
  • 이 범위를 벗어나면 이상치로 본다.

📍 Z-점수 기반 이상치 탐지

  • 데이터가 평균에서 몇 표준편차만큼 떨어져 있는지를 z-score로 계산해 이상치를 탐지한다.

⚖️데이터의 분포와 비대칭성

📍 왜도(skewness)

  • 데이터 분포가 평균을 중심으로 얼마나 비대칭적인지 나타내는 값.
  • 얼마나 치우쳐 있는지!!
  • 양의 방향으로 꼬리가 길면 최빈값 < 중앙값 < 평균, 음의 방향이면 이 반대이다.

📍 첨도(kurtosis)

  • 데이터 분포의 뾰족함 또는 평평함 정도를 나타내는 값.
  • 얼마나 뾰족한지!!

🔗변수 간 관계 이해

📍 상관계수(correlation coefficient)

  • 두 변수 간 선형적 관계의 방향과 강도를 -1에서 1 사이 값으로 나타낸다.
  • 부호는 방향, 절댓값은 강도를 의미한다.

📍 Cohen 기준 해석

  • 0.50 ~ 1.00 : 강한 상관관계
  • 0.30 ~ 0.49 : 중간 상관관계
  • 0.10 ~ 0.29 : 약한 상관관계

📍 헷갈리기 쉬운 점

상관계수가 -1에 가까울수록 상관관계가 없는 것이 아니다. 0에 가까울수록 상관관계가 거의 없는 것이고, -1은 강한 음의 상관관계다.

✏️기술 통계 코드 정리

📍 describe()

컬럼별 기본 통계 정보를 확인할 때 사용한다. 기본적으로는 수치형 데이터에 대해 계산된다.

df.describe()

 

모든 데이터 유형을 보고 싶다면 include='all'을 사용한다.

 

이때 출력값에서:

  • top은 최빈값
  • freq는 최빈값의 등장 횟수!
df.describe(include='all')

 

📍 최빈값 구하기

수치형 데이터에 대해 describe()를 해도 최빈값은 기본 출력에 포함되지 않는다. 최빈값은 mode()로 구한다. 여러 개면 여러 개 모두 나온다.

df['컬럼명'].mode()

 

📍 분산과 표준편차 구하기

df['컬럼명'].var()   # 분산
df['컬럼명'].std()   # 표준편차

 

표준편차는 describe() 결과에서도 바로 확인할 수 있다.

 

📍 누적값 계산하기

  • 누적 합
df['컬럼명'].cumsum()
  • 누적 곱
df['컬럼명'].cumprod()

🖍️pandas plot()으로 간단히 그리기

판다스에서도 간단한 시각화를 바로 할 수 있긴 하다. 기본은 선그래프이고, kind='bar' 이런식으로 유형 옵션을 주면 해당 그래프가 그려진다.

df['컬럼명'].plot()
df['컬럼명'].plot(kind='bar')

 

상자그림, 히스토그램, KDE도 이런식으로 간단히 그릴 수 있다. 빠르게 데이터를 탐색하기에 좋은 것같다.

df['컬럼명'].plot(kind='box')
df['컬럼명'].plot(kind='hist')
df['컬럼명'].plot(kind='kde')

📚데이터 시각화 라이브러리 개요

수업에서 강조하신 부분은, 그래프를 그리는 방식에 정답은 없다는 것이었다.어떤 라이브러리를 쓰느냐보다 더 중요한 것은 데이터의 내용을 전달하기 위해 어떤 시각화가 적합한지 판단하는 것이다. 즉, 코드를 외우는 것보다 그래프 선택 기준이 더 중요하다.

 

📍 주요 라이브러리 특징

  • matplotlib: 가장 기본적이고 강력한 시각화 라이브러리, 세밀한 커스터마이징 가능
  • seaborn: 통계적 시각화에 특화, 직관적이고 기본 스타일이 예쁨, 다만 커스터마이징에는 제약이 있음
  • plotly: interactive 시각화 지원, 줌/호버/클릭 등 상호작용 가능

📍 그래프별 용도

  • 막대그래프: 범주별 수치 비교, 빈도 및 비율 비교
  • 파이차트: 전체 대비 각 범주의 비율
  • 히스토그램: 데이터 분포 형태와 빈도 탐색
  • KDE plot: 분포를 부드러운 곡선 형태로 시각화
  • 라인그래프: 시간에 따른 변화
  • 면적그래프: 누적 변화 및 각 요소 변화량 분석
  • 산점도: 두 변수 간 상관관계 분석
  • 히트맵: 다변량 데이터의 상관관계 파악
  • 상자그림: 이상치, 중앙값, 사분위수 탐색

🌼Matplotlib 라이브러리

📍Matplotlib이란?!

matplotlib.pyplot은 파이썬에서 데이터를 시각화하는 대표적인 라이브러리이다. 세부 설정이 자유로워 맞춤형 시각화에 유리하다.
pyplot 모듈은 plt.plot(), plt.bar()처럼 명령형 방식으로 다양한 그래프를 쉽게 만들 수 있도록 도와준다.

import matplotlib.pyplot as plt

🖌️Matplotlib 으로 차트 만들기

1️⃣Line Plot

시간에 따른 변화 추이를 보여줄 때 사용한다. 데이터 포인트 간 연속성을 강조한다. (예: 월별 매출 변화, 온도 변화 추세)

plt.plot(x축_컬럼, y축_컬럼)
plt.show()

 

2️⃣Bar Plot

범주별 비교를 할 때 사용한다. 값의 크기 차이를 직관적으로 표현할 수 있다. (예: 부서별 인원 수, 제품별 판매량)

plt.bar(x축_컬럼, y축_컬럼)
plt.show()

 

3️⃣Scatter Plot

두 변수 간 관계를 점으로 표현하는 그래프다. 상관관계, 분포, 패턴 확인에 유용하다. 우상향이면 양의 상관관계, 우하향이면 음의 상관관계이다.

plt.scatter(x축_컬럼, y축_컬럼)
plt.show()

 

마커 색상과 모양도 지정할 수 있다. 마커 종류는 matplotlib 공식 문서에서 확인할 수 있다.
https://matplotlib.org/stable/api/markers_api.html#module-matplotlib.markers

plt.scatter(x축_컬럼, y축_컬럼, c='색깔', marker='종류')
plt.show()

 

4️⃣Box Plot

데이터 분포와 이상치를 시각적으로 보여주는 그래프이다. 여러 그룹 간 분포 비교에도 유용하며, IQR을 이용해 이상치를 판별한다.

 

상자그림 해석

  • 중앙선: 중앙값(Q2)
  • 상자 윗면: Q3
  • 상자 아랫면: Q1
  • 수염: 정상 범위 내 최솟값/최댓값
  • 점: 이상치
df['컬럼명'].plot(kind='box')
plt.show()

 

모든 컬럼에 대해 한 번에 그릴 수도 있다.

df.plot(kind='box')
plt.show()

 

주의할 점은 이상치 마커가 겹칠 수 있으므로 그림만 보고 이상치 개수를 단정하면 안 된다는 점이다.

 

5️⃣Histogram

수치형 데이터를 구간별로 나누어 각 구간에 속하는 데이터 개수를 막대 높이로 보여준다. 분포 형태와 패턴을 파악할 때 매우 유용하다.

 

언제 쓰는가?

  1. 데이터의 전반적 분포 파악
  2. 중심 경향과 변동성 확인
  3. 이상치 탐색 전 단계 확인
  4. 집단 간 분포 비교
  5. 정규성 판단

기본적으로 bins를 지정하지 않으면 구간을 10개로 나눈다. 상황에 맞게 적절한 구간 수를 정하는 것이 중요하다.

df['컬럼명'].plot(kind='hist')
plt.show()
df['컬럼명'].plot(kind='hist', bins=20)
plt.show()

 

6️⃣KDE Plot

표본 데이터를 바탕으로 확률 밀도 함수를 추정해 연속형 데이터 분포를 부드러운 곡선으로 표현한다. 히스토그램을 곡선화한 느낌으로 이해하면 된다.

df['컬럼명'].plot(kind='kde')
plt.show()

 

곡선의 세세함 정도는 bw_method로 조절한다. 숫자가 작을수록 더 세세하게 표현되고, 1 이상이면 더 완만해진다.

df['컬럼명'].plot(kind='kde', bw_method=0.1)
plt.show()

👩‍🎨Matplotlib 심화

📍Object-oriented 방식

matplotlib의 기본 동작 원리이다. 그림을 그릴 공간을 준비한 뒤, 그 안에 캔버스를 두고, 그 캔버스 위에 그래프를 그리는 방식이다. 복잡하고 정교한 시각화에 유리하다.

 

1️⃣Figure와 Axes

  • Figure: 그래프 전체를 담는 최상위 객체, 빈 공간
  • Axes: Figure 안에서 실제 그래프가 그려지는 영역, 캔버스
fig, ax = plt.subplots()

 

이렇게 하면

  • fig: 그림을 그릴 공간,
  • ax: 그래프를 그릴 캔버스가 생성된다.

2️⃣Object-oriented 방식으로 Line Plot 그리기 (예시)

fig, ax = plt.subplots()
ax.plot(x축_리스트, y축_리스트)
plt.show()

 

범주 a, b를 나눠 각각 그리고 싶다면 query() 등으로 필터링한 뒤 여러 번 ax.plot()을 사용한다.

fig, ax = plt.subplots()

a_df = df.query("컬럼명 == 'a'")
b_df = df.query("컬럼명 == 'b'")

ax.plot(a_df['x축'], a_df['y축'], label='legend a')
ax.plot(b_df['x축'], b_df['y축'], label='legend b')

ax.legend()
plt.show()

 

3️⃣제목, 축 이름, 범례 추가하기

fig, ax = plt.subplots()

ax.plot(df['x축'], df['y축'], label='line 1')
ax.legend()

ax.set_title('제목')
ax.set_xlabel('x축 제목')
ax.set_ylabel('y축 제목')

plt.show()

 

축 제목 위치도 조절할 수 있다. (location)

ax.set_xlabel('x축 제목', loc='left')
ax.set_ylabel('y축 제목', loc='bottom')

 

4️⃣한글 깨짐 해결

라벨이나 제목을 한글로 쓰면 깨지는 경우가 있다. 다음 코드로 한글 깨짐을 해결할 수 있다.

!pip install koreanize-matplotlib
import koreanize_matplotlib

 

이후에는 한글 제목, 축 이름, 범례를 편하게 쓸 수 있다!

 

5️⃣눈금(tick) 조정하기

  • 눈금 위치 지정
import numpy as np

ax.set_xticks(np.arange(범위_시작, 범위_끝, 간격))
ax.set_yticks(np.arange(범위_시작, 범위_끝, 간격))
  • 눈금 라벨 바꾸기
x_values = a_df['x축']
x_labels = [f"{i}단위" for i in x_values]

ax.set_xticks(x_values, labels=x_labels)
  • 눈금 기울이기

눈금 글자가 길어서 겹칠 때 사용한다.

ax.set_xticks(x_values, labels=x_labels, rotation=30)

 

6️⃣테두리(spine) 제거하기

spine은 그래프의 테두리 선을 뜻한다. 보통은 윗면과 오른쪽 면을 제거해서 더 깔끔하게 본다.

ax.spines[['top', 'right']].set_visible(False)

 

7️⃣격자선(grid) 추가하기

ax.grid(axis='y', linestyle=':', color='lightgrey')
  • axis='y': y축 방향 격자선
  • linestyle=':': 점선
  • color='lightgrey': 연한 회색 격자선

8️⃣선 스타일 커스터마이징

ax.plot(
    df['x축'],
    df['y축'],
    alpha=0.7,
    linewidth=2,
    linestyle='--',
    color='teal',
    marker='o'
)
  • alpha: 투명도
  • linewidth: 선 두께
  • linestyle: 선 스타일
  • color: 색
  • marker: 데이터 포인트 표시

9️⃣여러 개의 Axes 다루기

  • 1행 2열로 두 개의 그래프 만들기
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))

ax1.plot(a_df['x축'], a_df['y축'])
ax2.plot(b_df['x축'], b_df['y축'])

plt.show()

 

반복되는 설정이 많다면 axes로 받아 반복문을 쓸 수 있다.

fig, axes = plt.subplots(1, 2, figsize=(12, 4))

axes[0].plot(a_df['x축'], a_df['y축'])
axes[1].plot(b_df['x축'], b_df['y축'])

for ax in axes:
    ax.set_xlabel('x축 제목')
    ax.set_ylabel('y축 제목')
    ax.grid(axis='y', linestyle='--', color='lightgrey')
    ax.spines[['top', 'right']].set_visible(False)

plt.show()

 

실습에서는 teal, palevioletred, goldenrod 같은 색도 보여주셨다!

  • 세 개의 Axes 다루기
fig, (ax1, ax2, ax3) = plt.subplots(3, sharex=True, figsize=(8, 10), constrained_layout=True)

ax1.plot(a_df['x축'], a_df['y축'])
ax2.plot(b_df['x축'], b_df['y축'])
ax3.plot(c_df['x축'], c_df['y축'])

fig.suptitle('차트의 대제목', fontsize=14)
fig.supxlabel('x축의 대제목')
fig.supylabel('y축의 대제목')

for ax in [ax1, ax2, ax3]:
    ax.grid(axis='y', linestyle='--', color='lightgrey')
    ax.spines[['top', 'right']].set_visible(False)

plt.show()
  • sharex=True: x축 공유
  • constrained_layout=True: 간격 자동 조정
  • fig.suptitle(): 전체 그래프 대제목
  • fig.supxlabel(), fig.supylabel(): 전체 축 제목

 

📍State-based 방식

State-based는 이미 그래프를 그릴 캔버스가 있다고 가정하고 바로 그리는 방식이다. 간단한 그래프를 빠르게 만들 때 편하다.

plt.plot(x축, y축)
plt.show()
  • 두 개의 그래프 그리기
plt.subplot(1, 2, 1)
plt.plot(x1, y1)
plt.title('첫 번째 그래프')
plt.xlabel('x축')
plt.ylabel('y축')
plt.grid()

plt.subplot(1, 2, 2)
plt.plot(x2, y2)
plt.title('두 번째 그래프')
plt.xlabel('x축')
plt.ylabel('y축')
plt.grid()

plt.show()

 

Object-oriented와 다르게 plt.title(), plt.xlabel()처럼 직접 써야 해서 반복이 많아질 수 있다.

🎭Object-oriented vs State-based 비교

📍Object-oriented

  • 복잡하고 정교한 시각화에 유리
  • 여러 그래프를 다룰 때 구조적으로 관리하기 좋음
  • 세부 조정이 자유로움

📍State-based

  • 간단하게 바로 그리고 싶을 때 편함
  • 반복이 많아질 수 있음
  • 세밀한 제어에는 한계가 있음

결론적으로 둘 중 하나가 무조건 더 좋은 것은 아니고, 상황에 따라 다르다.

🌊Seaborn 라이브러리

📍Seaborn이란?!

seaborn은 matplotlib 기반의 통계 시각화 라이브러리이다. 코드가 간결하고 기본 스타일이 세련되어 있어, 빠르게 가독성 높은 그래프를 만들 수 있다.

import seaborn as sns

 

📍Matplotlib과 비교

  • matplotlib: 원하는 대로 세밀하게 커스터마이징 가능
  • seaborn: 기본 그래프가 깔끔하고 통계 시각화에 특화

🐳Seaborn 으로 차트 만들기

1️⃣Line Plot

sns.lineplot(data=df, x='x축_컬럼', y='y축_컬럼')
plt.show()

 

오차 막대를 없애고 싶다면:

sns.lineplot(data=df, x='x축_컬럼', y='y축_컬럼', errorbar=None)
plt.show()

 

범주별로 선을 나눠 보고 싶다면:

sns.lineplot(data=df, x='x축_컬럼', y='y축_컬럼', hue='컬럼명', errorbar=None)
plt.show()

 

2️⃣Bar Plot

sns.barplot(data=df, x='x축_컬럼', y='y축_컬럼')
plt.show()

 

오차 막대 제거:

sns.barplot(data=df, x='x축_컬럼', y='y축_컬럼', errorbar=None)
plt.show()

 

범주별 구분:

sns.barplot(data=df, x='x축_컬럼', y='y축_컬럼', hue='컬럼명', errorbar=None)
plt.show()

 

3️⃣Scatter Plot

두 연속형 변수의 관계를 점으로 나타낸다. 상관관계, 분산 정도, 이상치 확인에 유용하다. 추가 변수는 hue, style, size로 함께 표현할 수 있다.

sns.scatterplot(data=df, x='x축_컬럼', y='y축_컬럼')
plt.show()

 

4️⃣Regplot

산점도와 함께 회귀선을 그려주는 그래프다. 회귀선이 있으면 패턴을 더 쉽게 파악할 수 있다.

sns.regplot(data=df, x='x축_컬럼', y='y축_컬럼')
plt.show()

 

5️⃣Box Plot 

sns.boxplot(data=df, x='x축_컬럼', y='y축_컬럼')
plt.show()

 

범주의 순서를 직접 지정할 수도 있다.

sns.boxplot(data=df, x='x축_컬럼', y='y축_컬럼', order=['A', 'B', 'C'])
plt.show()

 

주의할 점은 중앙값으로 비교해야 한다는 것이다. 상자 윗면으로 해석하는 것이 아니라 상자 안 중앙선을 봐야 한다.

 

6️⃣Hist Plot

sns.histplot(data=df, x='x축_컬럼')
plt.show()

 

범주별 구분:

sns.histplot(data=df, x='x축_컬럼', hue='컬럼명')
plt.show()

 

누적 형태로 보고 싶다면:

sns.histplot(data=df, x='x축_컬럼', hue='컬럼명', multiple='stack')
plt.show()

 

7️⃣KDE Plot

sns.kdeplot(data=df, x='x축_컬럼')
plt.show()

 

면적 채우기:

sns.kdeplot(data=df, x='x축_컬럼', fill=True)
plt.show()

 

곡선의 세세함 조정:

sns.kdeplot(data=df, x='x축_컬럼', bw_method=0.1, fill=True)
plt.show()

 

8️⃣Violin Plot

boxplot에 KDE를 더한 형태다. 곡선으로 분포 밀도를 보여주고, 내부에 상자그림과 중앙값도 포함된다. 잘 사용하지는 않는다.

sns.violinplot(data=df, x='x축_컬럼', y='y축_컬럼')
plt.show()

 

9️⃣Strip Plot

범주형 데이터의 분포를 개별 점으로 표현한다. 데이터가 많아지면 점이 너무 많아질 수 있어 자주 쓰이지는 않는다.

sns.stripplot(data=df, x='x축_컬럼', y='y축_컬럼')
plt.show()

 

범주별 색 구분:

sns.stripplot(data=df, x='x축_컬럼', y='y축_컬럼', hue='컬럼명')
plt.show()

 

1️⃣0️⃣Swarm Plot

stripplot과 비슷하지만, 점이 겹치지 않도록 배치한다. 이 역시 데이터가 많으면 복잡해져서 자주 사용하지는 않는다.

sns.swarmplot(data=df, x='x축_컬럼', y='y축_컬럼')
plt.show()
sns.swarmplot(data=df, x='x축_컬럼', y='y축_컬럼', hue='컬럼명')
plt.show()

 

1️⃣1️⃣Correlation Heatmap

먼저 수치형 컬럼 간 상관관계를 계산한다.

df.corr(numeric_only=True)

 

그 후 heatmap으로 시각화한다.

sns.heatmap(df.corr(numeric_only=True))
plt.show()

 

숫자까지 같이 표시하고 싶다면:

sns.heatmap(df.corr(numeric_only=True), annot=True, fmt='.2f')
plt.show()
  • annot=True: 숫자 표시
  • fmt='.2f': 소수점 둘째 자리까지 표시

🐟seaborn 심화

핵심은 Figure-level 함수와 Axes-level 함수의 차이이다.

 

📍Figure-level vs Axes-level

 

Figure-level 함수

  • col, row 같은 옵션으로 그래프를 쉽게 분리해서 볼 수 있다
  • 그룹별로 나눠 보고 인사이트를 찾고 싶을 때 유리하다

Axes-level 함수

  • 더 직관적이고 명료하다
  • matplotlib 기반 추가 가공이 쉽다

📍Figure-level 그래프

 

1️⃣catplot

catplot은 categorical plot의 줄임말이다. 범주별 수치 비교를 위한 Figure-level 함수다. kind에 따라 여러 종류의 그래프를 만들 수 있다. (bar, count, strip, box, violin, swarm, box, point)

sns.catplot(data=df, x='x축', y='y축', kind='bar', errorbar=None)
plt.show()

 

다른 그래프도 kind만 바꾸면 된다.

sns.catplot(data=df, x='x축', y='y축', kind='box')
sns.catplot(data=df, x='x축', y='y축', kind='violin')
sns.catplot(data=df, x='x축', y='y축', kind='strip')

 

2️⃣relplot

relplot은 relational plot의 줄임말이다. 두 연속형 변수 간 관계를 나타낼 때 적합하다. scatter, line을 그릴 수 있다.

  • scatter
sns.relplot(data=df, x='x축', y='y축', kind='scatter')
plt.show()

 

col로 그래프를 나눠 볼 수 있다.

sns.relplot(data=df, x='x축', y='y축', kind='scatter', col='컬럼명')
plt.show()

  • line
sns.relplot(data=df, x='x축', y='y축', kind='line', errorbar=None)
plt.show()

 

하나의 화면에서 hue로 구분하거나:

sns.relplot(data=df, x='x축', y='y축', kind='line', hue='컬럼명', errorbar=None)
plt.show()

 

col로 쪼개서 볼 수도 있다.

sns.relplot(data=df, x='x축', y='y축', kind='line', col='컬럼명', errorbar=None)
plt.show()

 

3️⃣displot

displot은 distribution plot의 줄임말이다. 분포를 시각화할 때 사용하며, hist, kde, ecdf 등을 지원한다.

  • histogram
sns.displot(data=df, x='x축', kind='hist')
plt.show()

 

구간 수 조정:

sns.displot(data=df, x='x축', kind='hist', bins=20)
plt.show()

 

범주별 구분:

sns.displot(data=df, x='x축', kind='hist', hue='컬럼명')
plt.show()

 

그래프 나눠 보기:

sns.displot(data=df, x='x축', kind='hist', col='컬럼명', legend=False)
plt.show()

 

KDE 함께 보기:

sns.displot(data=df, x='x축', kind='hist', kde=True)
plt.show()

 

두 변수 분포 시각화

sns.displot(data=df, x='x축', y='y축', kind='hist')
sns.displot(data=df, x='x축', y='y축', kind='kde')
plt.show()

 

이런 2변수 분포 시각화는 거의 사용하지 않는다.

 

📍Axes-level 그래프

 

barplot 추가 옵션

sns.barplot(data=df, x='x축', y='y축', errorbar=None)
plt.show()

 

순서 조정

sns.barplot(data=df, x='x축', y='y축', errorbar=None, order=['A', 'B', 'C'])
plt.show()

 

estimator 변경

기본은 평균값이다. 필요하면 다른 집계 함수를 지정할 수 있지만, 대부분은 평균을 사용한다고 정리되어 있었다.

import numpy as np
sns.barplot(data=df, x='x축', y='y축', errorbar=None, estimator=np.median)
plt.show()

 

palette 지정

sns.barplot(data=df, x='x축', y='y축', errorbar=None, palette='deep')
plt.show()

 

seaborn 팔레트 문서를 참고하면 된다!

  • _d가 붙으면 dark 버전
  • _r가 붙으면 reversed 버전

🐬seaborn / matplotlib 커스터마이징 정리

📍seaborn으로 커스터마이징

 

1️⃣spine 제거

sns.despine()

 

기본적으로 위쪽과 오른쪽 선을 제거한다.

 

2️⃣범례 옮기기

ax = sns.barplot(data=df, x='x축', y='y축', hue='범주', errorbar=None)
sns.move_legend(ax, 'upper left')
plt.show()

 

기록에는 bbox_to_anchor=(1, 1)도 언급되어 있었다.

 

3️⃣전체 스타일 변경

sns.set_style('whitegrid')
sns.set_palette('deep')
sns.set_theme(style='whitegrid', palette='deep')

 

set_style 기본 옵션은 다음과 같다!

  • dark
  • white
  • darkgrid
  • whitegrid
  • ticks

4️⃣평균선 추가

ax = sns.boxplot(data=df, x='범주형컬럼', y='수치형컬럼')
ax.axhline(df['수치형컬럼'].mean(), color='red', linestyle='--')
plt.show()

 

📍matplotlib으로 커스터마이징 다시 정리

fig, ax = plt.subplots()

ax.set_title('제목')
ax.set_xlabel('x축 제목')
ax.set_ylabel('y축 제목')

ax.set_xlim([0, 100])
ax.set_ylim([0, 500])

ax.set_xticks([0, 20, 40, 60, 80, 100])
ax.set_yticks([0, 100, 200, 300, 400, 500])

ax.grid(axis='y', linestyle='--', color='lightgrey')

ax.axhline(df['컬럼명'].mean(), color='red', linestyle='--')

plt.show()
  • set_xlim(), set_ylim(): 축 범위 지정
  • set_xticks(), set_yticks(): 눈금 값 지정
  • axhline(): 평균선 추가

🧩Plotly 라이브러리

📍Plotly란?!

plotly는 최소한의 코드만으로도 상호작용이 가능한 동적 그래프를 그릴 수 있게 해주는 시각화 라이브러리다. 마우스를 올리면 값이 보이고, 줌이나 범례 클릭도 가능해서 데이터를 다각적으로 살펴보는 데 도움이 된다.

import plotly.express as px

🫧Plotly의 두 인터페이스

1️⃣Plotly Graph Objects

  • low-level 인터페이스
  • 세부 요소를 하나하나 직접 구성해야 함
  • 자유도는 높지만 코드가 길고 복잡해질 수 있음
import plotly.graph_objects as go

 

2️⃣Plotly Express

  • high-level 인터페이스
  • 빠르고 간단한 코드로 대부분의 작업 가능
  • (수업에서는 이것만 사용했음!)
import plotly.express as px

🎨Plotly express로 차트 만들기

📍비교 및 추세 시각화

 

1️⃣Bar Plot

px.bar(df, x='x축', y='y축')

 

범주별 색 구분:

px.bar(df, x='x축', y='y축', color='컬럼명')

 

기본적으로는 누적처럼 보여서 보기 어려울 수 있으므로, 그룹형으로 자주 바꾼다.

px.bar(df, x='x축', y='y축', color='컬럼명', barmode='group')

 

범주별로 그래프를 쪼개기:

px.bar(df, x='x축', y='y축', facet_col='컬럼명')
px.bar(df, x='x축', y='y축', facet_row='컬럼명')

 

 

2️⃣Line Plot

px.line(df, x='x축', y='y축')

 

범주별 색 구분:

px.line(df, x='x축', y='y축', color='컬럼명')

 

📍비중 및 구성 시각화

 

1️⃣Pie Chart

px.pie(df, values='비중_컬럼', names='범주형_컬럼')

 

그래프가 그려졌을 때, 범례에서 특정 범주를 클릭하면 제외하고 볼 수도 있다. 이런 점이 plotly의 interactive 한 장점이다.

 

2️⃣Treemap

트리맵은 계층 구조를 가진 데이터를 시각화할 때 효과적이다. 한 그룹 안에 또 다른 그룹이 포함되는 구조를 볼 때 유용하다.

px.treemap(df, path=['큰계층', '작은계층'], values='비중_컬럼')

 

3️⃣Sunburst Chart

태양이 퍼져 나가는 형태처럼 보이는 계층 구조 차트다. 계층 구조 시각화에 적합하지만, 범주가 너무 많아지면 읽기 어려워진다.

px.sunburst(df, path=['큰계층', '작은계층'], values='비중_컬럼')

 

색도 함께 지정할 수 있다.

px.sunburst(df, path=['큰계층', '작은계층'], values='비중_컬럼', color='컬럼명')

 

📍분포 시각화

 

1️⃣Strip Plot

자주 쓰지는 않으며, 특히 데이터가 많을 때 겹쳐 보일 수 있다.

px.strip(df, x='범주형컬럼', y='수치형컬럼')

 

2️⃣Box Plot

실무에서는 seaborn boxplot을 더 많이 쓴다고 한다.

px.box(df, x='범주형컬럼', y='수치형컬럼')

 

3️⃣Violin Plot

자주 사용하지는 않는다. 차트가 이름 그대로 바이올린 모양을 띤다.

px.violin(df, x='범주형컬럼', y='수치형컬럼')

 

4️⃣Histogram

px.histogram(df, x='수치형컬럼')

 

📍산점 및 관계 시각화

 

1️⃣산점도

px.scatter(df, x='x축', y='y축')

 

hover_name은 마우스를 올렸을 때 어떤 컬럼을 대표 정보로 보여줄지 정한다.

px.scatter(df, x='x축', y='y축', hover_name='컬럼명')

 

색 구분:

px.scatter(df, x='x축', y='y축', color='컬럼명')
  • 범주형이면 범주별 색
  • 수치형이면 연속형 컬러 스케일이 적용된다.

마커 모양 구분:

px.scatter(df, x='x축', y='y축', symbol='컬럼명')

 

2️⃣Bubble Chart

산점도에 size만 추가하면 된다. 값 크기에 따라 버블 크기가 달라진다.

px.scatter(df, x='x축', y='y축', size='크기에_영향을_줄_컬럼명')

 

최대 버블 크기 조정:

px.scatter(df, x='x축', y='y축', size='크기컬럼', size_max=60)

 

3️⃣Dot Plot

산점도의 변형 형태이다. 변수 둘 중 하나는 범주형이어야 한다. 많이 쓰지는 않는다.

 

📍Funnel Chart

 

퍼널은 깔때기라는 뜻이다. 퍼널 분석은 유저 행동의 연속적인 단계를 수치로 확인하는 분석 방법이다. 위 단계에서 아래 단계로 갈수록 유저 수가 줄어드는 모습이 깔때기처럼 보여서 퍼널이라고 한다. 예시로는 다음과 같다.

  • 사이트 방문
  • 상품 상세 페이지 확인
  • 장바구니 담기
  • 구매

이 부분은 Part 2에서 더 자세히 배운다고 한다.

📐Plotly Express 활용

1️⃣제목 붙이기

px.bar(df, x='x축', y='y축', title='제목')

 

2️⃣변수명 변경하기

축 제목과 범례명을 바꿀 수 있다.

px.bar(
    df,
    x='old_x',
    y='old_y',
    color='old_color',
    labels={
        'old_x': '새 x축 이름',
        'old_y': '새 y축 이름',
        'old_color': '새 범례명'
    }
)

 

3️⃣값의 순서 조정하기

px.bar(
    df,
    x='변수1',
    y='값',
    color='변수2',
    category_orders={
        '변수1': ['A', 'B', 'C'],
        '변수2': ['X', 'Y', 'Z']
    }
)

 

4️⃣색상 팔레트 변경

  • 범주형 색상
px.bar(
    df,
    x='x축',
    y='y축',
    color='범주형컬럼',
    color_discrete_sequence=px.colors.qualitative.Set2
)
  • 연속형 색상
px.scatter(
    df,
    x='x축',
    y='y축',
    color='수치형컬럼',
    color_continuous_scale='Viridis'
)

 

5️⃣막대 위에 값 표시하기

px.bar(df, x='x축', y='y축', text_auto=True)

 

 

6️⃣천 단위 콤마 표시하기

px.bar(df, x='x축', y='y축', text_auto=',d')

 

7️⃣그래프 크기 지정하기

px.bar(df, x='x축', y='y축', height=500, width=900)

 

8️⃣hover 요소 다루기

  • hover_name 지정
px.scatter(df, x='x축', y='y축', hover_name='컬럼명')

 

  • hover_data 지정
px.scatter(df, x='x축', y='y축', hover_data=['컬럼명1', '컬럼명2'])
  • hovermode 설정

차트를 변수에 할당한 뒤 설정한다.

fig = px.line(df, x='x축', y='y축', color='범주')

fig.update_traces(hovertemplate=None)
fig.update_layout(hovermode='x')

fig.show()

 

한 번에 하나의 박스로 묶어 보기:

fig = px.line(df, x='x축', y='y축', color='범주')

fig.update_traces(hovertemplate=None)
fig.update_layout(hovermode='x unified')

fig.show()

 

9️⃣그래프 공유하기

plotly 차트는 HTML로 저장해서 공유할 수 있다.

fig = px.bar(df, x='x축', y='y축')
fig.write_html('파일명.html')

🖼️라이브러리별 정리 한눈에 보기

📍Matplotlib

  • 가장 기본적이고 강력한 시각화 라이브러리
  • 세밀한 커스터마이징에 강함
  • Object-oriented / State-based 두 방식 존재
  • 복잡한 그래프 제어에 적합

📍Seaborn

  • matplotlib 기반 통계 시각화 라이브러리
  • 코드가 간결하고 기본 스타일이 예쁨
  • Figure-level / Axes-level 함수 구분
  • 빠르게 가독성 높은 그래프를 만들기 좋음

📍Plotly

  • interactive 그래프 지원
  • 마우스 오버, 줌, 클릭 가능
  • Plotly Express는 빠르고 간단하게 사용 가능
  • 탐색형 시각화에 특히 유리

👏마무리

이번 수업에서는 단순히 그래프를 그리는 법만 배운 것이 아니라, 데이터의 대표값과 분포를 이해하고, 목적에 맞는 그래프를 고르는 기준까지 함께 정리할 수 있었다. 특히 같은 시각화라도 matplotlib, seaborn, plotly가 각각 역할이 다르기 때문에, 앞으로는 무조건 하나만 쓰기보다 상황에 따라 적절한 라이브러리를 고르는 것이 중요하다는 점을 다시 정리할 수 있었다. 하지만.. ㅎㅎ 지금까지 들었던 이론 강의들 중에서 이번 내용이 가장 정리하기 어려웠고, 배우면 배울수록 끝이 없다는 느낌이 가장 강하게 들었던 주제였던 것 같다.ㅋㅋ 특히 커스터마이징 방법은 하나를 찾으면 또 다른 방법이 나오고, 또 그걸 보다 보면 새로운 옵션이 나오는 식이라 정말 무슨 양파마냥.. 끝없이 이어지는 느낌이었다.

 

그래프 종류도 워낙 다양하다 보니, 나중에 실제로 시각화를 할 때는 어떤 라이브러리를 사용할지부터 어떤 차트를 선택할지, 어떤 구조로 배치할지, 또 어떤 방식으로 꾸밀지까지 생각해야 할 부분이 정말 많을 것 같다. 그래서 이번에 정리한 글은 어디까지나 기본적인 내용 중심의 정리라고 생각하고, 앞으로는 직접 구글링도 해보고 스프린트 미션을 하면서 여러 차트를 만들어보며 라이브러리 하나하나에 익숙해질 수 있도록 해야겠다는 생각이 들었다. 정리하는 과정은 정말 쉽지 않았지만, 그래도 한 번 이렇게 쭉 정리해두고 나니 나중에 다시 찾아볼 때는 분명 도움이 많이 될 것 같다. 시각화 고생했다!!!