CS/Python

파이썬으로 데이터 시각화 찍먹하기

munsik22 2026. 8. 6. 20:15

🧩 Matplotlib란?

Matplotlib은 파이썬에서 정적, 애니메이션 및 대화형 시각화를 생성하기 위한 포괄적인 라이브러리다. (Matplotlib 공식 사이트 발췌)

 

Matplotlib는 파이썬에서 데이터를 그래프로 시각화하는 대표적인 라이브러리다. Numpy 배열이나 Pandas의 DataFrame, Series 데이터를 선/막대 그래프, 산점도, 히스토그램 등으로 표현할 수 있다.

Figures와 Axes

  • Figure: 그래프 전체가 들어가는 큰 캔버스 (= 도화지 전체)
  • Axes: 실제 그래프가 그려지는 영역 (= 도화지 안의 그래프 1개)
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

ax.plot([1, 2, 3], [10, 20, 15])

plt.show()

plot(): 선 그래프

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [10, 15, 8, 20, 18]

plt.plot(x, y)
plt.show()

그래프에 제목과 축 이름 추가하기

함수 역할
plt.title() 그래프 제목
plt.xlabel() x축 이름
plt.ylabel() y축 이름
plt.xlim() x축 범위
plt.ylim() y축 범위
plt.grid() 격자 표시
plt.legend() 범례 표시
plt.plot(x, y, label="Sales")
plt.title("Daily Sales")
plt.xlabel("Day")
plt.ylabel("Sales")
plt.grid(True)
plt.legend()

plt.show()

⚠️ 한글 텍스트가 깨질 때

Matplotlib의 기본 폰트가 한글을 지원하지 않기 때문에 제목에 한글을 그냥 쓰면 깨져서 나온다.

plt.plot(x, y)
plt.title("일별 판매량")
plt.xlabel("날짜")
plt.ylabel("판매량")

plt.show()

운영체제에 따라 한글 폰트를 설정해야 한다.

# Windows
plt.rcParams["font.family"] = "Malgun Gothic"

# MacOs
plt.rcParams["font.family"] = "AppleGothic"

# Linux
plt.rcParams["font.family"] = "NanumGothic"

# '-' 기호가 깨지는 현상 방지
plt.rcParams["axes.unicode_minus"] = False

그래프 서식 바꾸기

옵션 의미
color 선 색상
linestyle 선 스타일
marker 데이터 지점 모양
linewidth 선 두께
label 범례에 표시할 이름
plt.plot(
    x, y,
    color="red",
    linestyle="--",
    marker="o",
    linewidth=2,
    label="Sales"
)
# 또는 plt.plot(x, y, "ro--")

plt.legend()

plt.show()

bar(): 막대 그래프

범주별 값을 비교할 때 사용한다. (부서별 인원, 상품별 판매량, 월별 매출 등)

names = ["Apple", "Banana", "Orange"]
sales = [30, 20, 25]

plt.bar(names, sales, color="skyblue")
plt.title("Fruit Sales")
plt.xlabel("Fruit")
plt.ylabel("Sales")

plt.show()

가로 막대 그래프는 barh()를 사용한다.

plt.barh(names, sales)
plt.title("Fruit Sales")
plt.xlabel("Fruit")
plt.ylabel("Sales")

plt.show()

scatter(): 산점도

두 변수 사이의 관계나 분포를 확인할 때 사용한다. (공부시간-시험점수, 키-몸무게, 광고비-매출 등)

import seaborn as sns
import matplotlib.pyplot as plt

iris = sns.load_dataset('iris')

plt.scatter(iris['sepal_length'], iris['sepal_width'], c='pink', alpha=0.6)
plt.xlabel('Sepal Length')
plt.ylabel('Sepal Width')

plt.show()

hist(): 히스토그램

데이터가 어떤 구간에 많이 분포하는지 확인할 때 사용한다.

scores = np.random.normal(70, 10, 100)

plt.hist(scores, bins=10, color="skyblue", edgecolor="black")

plt.title("Score Distribution")
plt.xlabel("Score")
plt.ylabel("Count")

plt.show()

히스토그램의 각 막대별로 다른 색을 지정할 수도 있다.

import numpy as np

scores = np.random.randn(1000)

n, bins, patches = plt.hist(scores, bins=20, edgecolor="black")

colors = plt.get_cmap('rainbow')(np.linspace(0, 1, len(patches)))
for patch, color in zip(patches, colors):
    patch.set_facecolor(color)

plt.show()

pie(): 원 그래프

전체 중 각 항목이 차지하는 비율을 보여줄 때 사용한다.

labels = ["Python", "Java", "C++", "JavaScript"]
sizes = [40, 25, 15, 20]

plt.pie(sizes, labels=labels, autopct="%.1f%%")
plt.title("Programming Language Preference")

plt.show()

 

boxplot(): 박스플롯

여러 범주의 분포를 비교할 때 사용한다.

data = [10, 20, 30, 40, 50, 60, 70, 100]

plt.boxplot(data)
plt.show()

data1 = [12, 25, 30, 35, 40, 55]
data2 = [20, 22, 28, 33, 45, 60]
data3 = [15, 18, 25, 42, 48, 75]

plt.figure(figsize=(8, 5))
box = plt.boxplot([data1, data2, data3], 
                  tick_labels=['Group A', 'Group B', 'Group C'],
                  patch_artist=True)

colors = ['pink', 'lightblue', 'lightgreen']
for patch, color in zip(box['boxes'], colors):
    patch.set_facecolor(color)

plt.show()

여러 데이터를 한 그래프에 표시하기

x = [1, 2, 3, 4, 5]
sales_a = [10, 15, 8, 20, 18]
sales_b = [8, 12, 14, 16, 22]

plt.plot(x, sales_a, marker="o", label="Store A")
plt.plot(x, sales_b, marker="s", label="Store B")

plt.title("Store Sales Comparison")
plt.xlabel("Day")
plt.ylabel("Sales")
plt.legend()
plt.grid(True)

plt.show()

여러 그래프를 한 화면에 표시하기

x = [1, 2, 3, 4]
y1 = [10, 20, 15, 25]
y2 = [5, 12, 18, 10]

fig, axes = plt.subplots(1, 2, figsize=(10, 4)) # 1행 2열로 그래프 영역 생성

axes[0].plot(x, y1, color="blue")
axes[0].set_title("Line Chart")

axes[1].bar(x, y2, color="orange")
axes[1].set_title("Bar Chart")

plt.tight_layout() # 그래프끼리 겹치지 않게 간격 자동 조절
plt.show()

Pandas 데이터 사용하기

df = pd.DataFrame({
    "월": ["1월", "2월", "3월", "4월"],
    "매출": [100, 120, 90, 150]
})

#plt.plot(df["월"], df["매출"], marker="o")
#plt.title("월별 매출액")
#plt.xlabel("월")
#plt.ylabel("매출")

# Pandas 자체에도 plot() 기능이 있으며, 내부적으로 Matplotlib을 사용함
df.plot(x="월", y="매출", kind="line", marker="o",
        title="월별 매출액", xlabel="월", ylabel="매출")

plt.show()

🧩 Seaborn이란?

Seaborn은 매력적이고 유익한 통계 그래프를 그리기 위한 고급 인터페이스를 제공하는 matplotlib 기반의 파이썬 데이터 시각화 라이브러리다. (Seaborn 공식 사이트 발췌)

 

Seaborn은 통계적 데이터 시각화에 특화된 파이썬 라이브러리다. Matplotlib을 기반으로 만들어졌기 때문에 내부적으로 Matplotlib를 사용하지만, 더 적은 코드로 보기 좋은 그래프를 만들 수 있다.

Seaborn vs Matplotlib

Matplotlib는 매우 유연하고 기본적인 시각화 도구다. Seaborn은 Pandas DataFrame과 범주형 데이터를 편하게 다룰 수 있고, 통계 정보도 함께 표현하기 좋다.

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

height = [160, 165, 170, 175, 180]
weight = [55, 60, 68, 72, 80]

df = pd.DataFrame({ "height": height, "weight": weight })

plt.scatter(df["height"], df["weight"])
plt.show() # Fig 1

sns.scatterplot(data=df, x="height", y="weight")
plt.show() # Fig 2
Fig 1 Fig 2
구분 Matplotlib Seaborn
특징 기본적이고 자유도가 높음 통계 시각화에 편리
디자인 직접 설정이 많이 필요함 기본 스타일이 깔끔함
Pandas DataFrame 열을 직접 지정하는 경우가 많음 data=df, x="열" 방식이 편리함
범주형 데이터 직접 구현이 필요한 경우가 있음 hue, style, col 등이 편리
통계 정보 직접 계산하는 경우가 많음 평균, 회귀선, 신뢰구간 등 자동 표시 가능

 

일반적으로 Seaborn은 빠르계 통계 그래프를 만드는데, Matplotlib는 세부적인 디자인을 조정하거나 복잡한 그래프를 구성하는 데 사용한다고 한다.

Theme 설정

sns.set_theme(style="whitegrid")  # 흰 배경 + 격자
sns.set_theme(style="darkgrid")   # 어두운 배경 + 격자
sns.set_theme(style="white")      # 흰 배경
sns.set_theme(style="dark")       # 어두운 배경
sns.set_theme(style="ticks")      # 축 눈금 강조

sns.barplot(x=["A", "B", "C"], y=[1, 3, 2])
plt.show()
whitegrid darkgrid

샘플 데이터셋

Seaborn은 다양한 연습용 데이터셋을 제공한다.

# 사용 가능한 데이터셋 목록
sns.get_dataset_names()

# tips 데이터셋 불러오기
tips = sns.load_dataset("tips")
print(tips.head())
'''
   total_bill   tip     sex smoker  day    time  size
0       16.99  1.01  Female     No  Sun  Dinner     2
1       10.34  1.66    Male     No  Sun  Dinner     3
2       21.01  3.50    Male     No  Sun  Dinner     3
3       23.68  3.31    Male     No  Sun  Dinner     2
4       24.59  3.61  Female     No  Sun  Dinner     4
'''

관계 그래프

  • scatterplot(): 산점도 그래프 ― 두 수치형 변수 사이의 관계
sns.scatterplot(
    data=tips,
    x="total_bill",
    y="tip",
    hue="sex",      # 성별에 따라 색상 구분
    style="smoker", # 흡연 여부별 마커 모양
    size="size",    # 인원수에 따라 점 크기 변경
    alpha=0.75
)

plt.title("Total Bill and Tip")
plt.show()

  • lineplot(): 선 그래프 ― 시간, 날짜, 순서에 따른 변화 추이 표현
flights = sns.load_dataset("flights")

sns.lineplot(
    data=flights,
    x="year",
    y="passengers",
    hue="month"
)

plt.title("Number of Passengers by Year")
plt.show()

범주형 그래프

성별, 요일, 등급, 부서 등 카테고리별 데이터를 쉽게 시각화할 수 있다.

  • barplot(): 막대 그래프 ― 범주별 평균값 비교
# 성별에 따른 요일별 평균 식사 금액
sns.barplot(
    data=tips,
    x="day",
    y="total_bill",
    hue="sex"
)

plt.title("Average Total Bill by Day")
plt.show()

기본적으로 barplot()은 평균값을 표시한다. 수직선은 오차범위를 의미하며 짧을수록 신뢰도가 커진다.

  • countplot(): 개수 그래프 ― 각 범주에 데이터가 몇 개씩 있는지 확인
# 흡연 여부에 따른 요일별 주문 건수
sns.countplot(
    data=tips,
    x="day",
    hue="smoker"
)

plt.title("Number of Records by Day")
plt.show()

  • boxplot(): 박스플롯 ― 데이터의 분포, 중앙값, 이상치 등 확인
# 성별에 따른 요일별 식사 금액 분포
sns.boxplot(
    data=tips,
    x="day",
    y="total_bill",
    hue="sex"
)

plt.title("Total Bill Distribution by Day")
plt.show()

- 상자 중앙선: 중앙값
- 상자 아래/위: 1/3사분위수
- 수염: 일반적인 데이터 범위
- 수염 밖 점: 이상치 가능성이 있는 값
  • violinplot(): 바이올린 플롯 ― 데이터가 많이 분포한 구간을 폭으로 표현
sns.violinplot(
    data=tips,
    x="day",
    y="total_bill"
)

plt.show()

  • stripplot() / swarmplot(): 점 그래프 ― 원본 데이터 점들을 볼 때 사용
sns.stripplot(
    data=tips,
    x="day",
    y="total_bill"
)

plt.show() # Fig 1

sns.swarmplot( # 점이 겹치지 않게 자동 정렬
    data=tips,
    x="day",
    y="total_bill"
)

plt.show() # Fig 2
Fig 1 Fig 2

분포 그래프

  • histplot(): 히스토그램
sns.histplot(
    data=tips,
    x="total_bill",
    hue="sex",
    bins=20,
    kde=True # 부드러운 분포 곡선 추가
)

plt.show()

  • kdeplot(): KDE 그래프 ― 데이터 분포를 부드러운 곡선으로 표현
sns.kdeplot(
    data=tips,
    x="total_bill",
    fill=True
)

plt.show()

  • displot(): 분포 종합 그래프

회귀선 그래프

  • regplot(): 두 변수의 관계와 회귀선을 함께 보고 싶을 때
sns.regplot(
    data=tips,
    x="total_bill",
    y="tip"
)

plt.show()

반투명 영역은 회귀 추정의 불확실성을 나타내는 신뢰구간

  • lmplot(): 범주별 회귀선을 보고 싶을 때

상관관계 히트맵

  • heatmap(): 히트맵 ― 데이터프레임의 수치형 열들 사이 상관관계를 볼 때
data = sns.load_dataset("titanic")
corr = data.select_dtypes("number").corr()

sns.heatmap(
    corr,
    annot=True,
    cmap="coolwarm",
    vmin=-1,
    vmax=1
)

plt.title("Correlation Heatmap")
plt.show()

상관계수의 절댓값이 1에 가까울수록 상관관계가 강하다.

  • 마스킹 적용하기
n = len(corr)

mask1 = np.triu(np.ones((n, n)), k=0) # default
sns.heatmap(corr, annot=True, fmt=".2f", cmap="RdBu_r", mask=mask1)
plt.show() # Fig 1

mask2 = np.triu(np.ones((n, n)), k=1)
sns.heatmap(corr, annot=True, fmt=".2f", cmap="RdBu_r", mask=mask2)
plt.show() # Fig 2

mask3 = np.triu(np.ones((n, n)), k=-1)
sns.heatmap(corr, annot=True, fmt=".2f", cmap="RdBu_r", mask=mask3)
plt.show() # Fig 3

mask4 = np.tril(np.ones((n, n)))
sns.heatmap(corr, annot=True, fmt=".2f", cmap="RdBu_r", mask=mask4)
plt.show() # Fig 4
Fig 1 Fig 2
Fig 3 Fig 4

여러 변수 관계 보기

  • pairplot(): 수치형 변수들이 서로 어떤 관계를 가지는지 확인 가능
sns.pairplot(iris, hue="species")

plt.show()

대각선 칸은 각 변수의 분포를, 나머지 칸은 변수 간 산점도를 나타낸다.

범주별 그래프 나누기

  • relplot(): 산점도, 선 그래프
  • displot(): 히스토그램, KDE 등 분포 그래프
  • catplot(): 막대, 박스, 바이올린 등 범주형 그래프
  • lmplot(): 회귀선 그래프
sns.relplot(data=tips, x="total_bill", y="tip", col="time", hue="sex")
plt.show() # Fig 1

sns.catplot(data=tips, x="day", y="total_bill", kind="box", col="time")
plt.show() # Fig 2
Fig 1 Fig 2

Axes-level 함수와 Figure-level 함수

  • Axes-level 함수: 이미 만들어진 Matplotlib Axes에 그래프를 그린다. ax=axes[0]처럼 어느 영역에 그릴지 지정할 수 있어 여러 그래프 배치에 좋다.
sns.scatterplot()
sns.lineplot()
sns.barplot()
sns.boxplot()
sns.histplot()
sns.heatmap()
sns.regplot()
  • Figure-level 함수: 그래프 전체 Figure를 자체적으로 생성한다. 여러 개의 그래프를 범주 별로 나누는 데 편리하다.
sns.relplot()
sns.displot()
sns.catplot()
sns.lmplot()
sns.pairplot()