데이터를 표로만 보면 전체 패턴을 빠르게 파악하기 어렵다.
시각화를 사용하면 다음과 같은 질문에 더 쉽게 답할 수 있다.
Python 데이터 분석에서는 주로 Matplotlib, Seaborn, 그리고 Pandas의 plot() 기능을 사용한다.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
Matplotlib는 기본 그래프 엔진 역할을 하고, Seaborn과 Pandas 시각화도 내부적으로 Matplotlib와 연결되는 경우가 많다.
days = [
1,
2,
3,
4,
5,
]
users = [
120,
150,
143,
190,
230,
]
plt.plot(
days,
users,
)
plt.xlabel("Day")
plt.ylabel("Users")
plt.title(
"Daily Active Users"
)
plt.show()
선 그래프는 순서가 있는 값의 변화, 특히 시간 변화에 적합하다.
Matplotlib를 제대로 사용하려면 두 객체를 구분하는 것이 좋다.
Figure: 전체 그림 영역Axes: 실제 그래프가 그려지는 영역fig, ax = plt.subplots()
ax.plot(
days,
users,
)
ax.set_title(
"Daily Active Users"
)
ax.set_xlabel("Day")
ax.set_ylabel("Users")
plt.show()
간단한 그래프에서는 plt.plot()도 충분하지만, 그래프가 복잡해질수록 객체 지향 방식인 fig, ax를 사용하는 것이 관리하기 쉽다.
fig, axes = plt.subplots(
1,
2,
figsize=(
10,
4,
),
)
첫 번째 그래프:
axes[0].plot(
days,
users,
)
axes[0].set_title(
"Users"
)
두 번째 그래프:
revenue = [
10,
12,
11,
16,
20,
]
axes[1].plot(
days,
revenue,
)
axes[1].set_title(
"Revenue"
)
레이아웃 정리:
fig.tight_layout()
plt.show()
범주별 값을 비교할 때 적합하다.
categories = [
"Search",
"Feed",
"Profile",
]
counts = [
320,
510,
180,
]
fig, ax = plt.subplots()
ax.bar(
categories,
counts,
)
ax.set_ylabel(
"Clicks"
)
ax.set_title(
"Clicks by Feature"
)
plt.show()
항목명이 길다면 가로 형태가 편할 수 있다.
fig, ax = plt.subplots()
ax.barh(
categories,
counts,
)
plt.show()
두 수치형 변수의 관계를 확인한다.
ad_spend = np.array(
[
10,
20,
30,
40,
50,
]
)
sales = np.array(
[
15,
24,
33,
41,
58,
]
)
fig, ax = plt.subplots()
ax.scatter(
ad_spend,
sales,
)
ax.set_xlabel(
"Ad Spend"
)
ax.set_ylabel(
"Sales"
)
plt.show()
두 변수가 함께 증가하는지, 이상한 점이 있는지 빠르게 확인할 수 있다.
수치형 데이터의 분포를 확인한다.
rng = np.random.default_rng(
42
)
response_time = rng.normal(
loc=200,
scale=40,
size=1000,
)
fig, ax = plt.subplots()
ax.hist(
response_time,
bins=30,
)
ax.set_xlabel(
"Response Time (ms)"
)
ax.set_ylabel(
"Count"
)
plt.show()
bins 값에 따라 그래프 인상이 크게 달라질 수 있으므로 여러 구간 수를 비교해보는 것이 좋다.
분포와 이상치를 빠르게 비교하는 데 유용하다.
fig, ax = plt.subplots()
ax.boxplot(
response_time
)
plt.show()
박스플롯은 일반적으로 다음 정보를 보여준다.
fig, ax = plt.subplots()
ax.pie(
[
50,
30,
20,
],
labels=[
"Web",
"App",
"Other",
],
autopct="%.1f%%",
)
plt.show()
전체에서 몇 개 항목이 차지하는 비율을 단순하게 보여줄 때 사용할 수 있다.
하지만 항목이 많거나 값 차이가 작다면 막대 그래프가 비교하기 더 쉬운 경우가 많다.
fig, ax = plt.subplots()
ax.plot(
days,
users,
label="Users",
)
ax.plot(
days,
revenue,
label="Revenue",
)
ax.legend()
plt.show()
ax.set_xlim(
1,
5,
)
ax.set_ylim(
0,
250,
)
눈금 직접 설정:
ax.set_xticks(
[
1,
2,
3,
4,
5,
]
)
축을 임의로 잘라 과장된 차이를 만들지 않도록 주의해야 한다.
Seaborn은 Pandas DataFrame의 컬럼명을 직접 지정할 수 있고, 범주별 색상·스타일 같은 통계적 시각화를 편하게 구성할 수 있다.
예제 데이터:
df = pd.DataFrame(
{
"channel": [
"search",
"search",
"feed",
"feed",
"profile",
"profile",
],
"session_time": [
12,
18,
25,
31,
9,
14,
],
"purchase": [
0,
1,
1,
1,
0,
0,
],
}
)
sns.scatterplot(
data=df,
x="session_time",
y="purchase",
hue="channel",
)
plt.show()
hue를 지정하면 그룹을 시각적으로 구분할 수 있다.
style, size도 데이터 의미에 따라 사용할 수 있지만, 너무 많은 시각 변수를 한 번에 넣으면 그래프가 복잡해질 수 있다.
sns.histplot(
data=df,
x="session_time",
bins=5,
)
plt.show()
그룹별 분포:
sns.histplot(
data=df,
x="session_time",
hue="channel",
)
plt.show()
필요하면 KDE를 함께 표시할 수도 있다.
sns.histplot(
data=df,
x="session_time",
kde=True,
)
plt.show()
sns.boxplot(
data=df,
x="channel",
y="session_time",
)
plt.show()
카테고리별 수치 분포 비교에 적합하다.
sns.violinplot(
data=df,
x="channel",
y="session_time",
inner="box",
)
plt.show()
박스플롯보다 분포 형태를 더 자세하게 보여준다.
데이터가 너무 적으면 밀도 모양을 과하게 해석하지 않도록 주의해야 한다.
sns.boxplot(
data=df,
x="channel",
y="session_time",
)
sns.stripplot(
data=df,
x="channel",
y="session_time",
)
plt.show()
요약 통계와 실제 점을 함께 보면 데이터 수와 분포를 더 정확하게 이해할 수 있다.
Series와 DataFrame에는 plot() 메서드가 있다.
sales = pd.Series(
[
120,
150,
180,
],
index=[
"Jan",
"Feb",
"Mar",
],
)
sales.plot()
plt.show()
sales.plot.bar()
plt.show()
df["session_time"].plot.hist(
bins=5
)
plt.show()
df[
[
"session_time",
"purchase",
]
].plot.box()
plt.show()
DataFrame의 두 컬럼:
numeric_df = pd.DataFrame(
{
"clicks": [
3,
5,
8,
10,
],
"orders": [
0,
1,
2,
4,
],
}
)
numeric_df.plot.scatter(
x="clicks",
y="orders",
)
plt.show()
간단한 EDA에서는 Pandas plot()이 빠르고 편하다.
세밀한 제어가 필요하면 Matplotlib나 Seaborn으로 확장할 수 있다.
summary = (
df
.groupby(
"channel"
)["session_time"]
.mean()
)
summary.plot.bar()
plt.ylabel(
"Average Session Time"
)
plt.show()
Pandas 분석 결과를 바로 그래프로 이어갈 수 있다.
dates = pd.date_range(
start="2026-09-01",
periods=30,
freq="D",
)
rng = np.random.default_rng(
42
)
traffic = pd.Series(
rng.integers(
100,
300,
size=30,
),
index=dates,
)
fig, ax = plt.subplots(
figsize=(
10,
4,
)
)
ax.plot(
traffic.index,
traffic.values,
)
ax.set_title(
"Daily Traffic"
)
plt.show()
시간의 흐름이 있는 데이터는 날짜 순서를 유지하는 것이 중요하다.
moving_average = (
traffic
.rolling(
window=7
)
.mean()
)
fig, ax = plt.subplots(
figsize=(
10,
4,
)
)
ax.plot(
traffic.index,
traffic.values,
label="Daily",
)
ax.plot(
moving_average.index,
moving_average.values,
label="7-day MA",
)
ax.legend()
plt.show()
원 데이터의 단기 변동과 추세를 함께 볼 수 있다.
| 질문 | 추천 그래프 |
|---|---|
| 시간에 따른 변화 | 선 그래프 |
| 범주별 크기 비교 | 막대 그래프 |
| 두 수치 변수 관계 | 산점도 |
| 하나의 수치 분포 | 히스토그램 |
| 그룹별 분포 비교 | 박스플롯 / 바이올린플롯 |
| 전체 중 몇 개 범주 비율 | 파이 차트 |
| 2차원 격자 값 | heatmap / image 계열 |
그래프 종류보다 분석 질문에 맞는 시각화인지가 더 중요하다.
일반적인 데이터 분석에서는 자주 사용하지 않지만, 관측 지점이 규칙적인 직사각형 격자가 아닐 때 Matplotlib의 삼각 분할 기반 그래프를 사용할 수 있다.
관련 함수:
plt.triplot(...)
plt.tripcolor(...)
plt.tricontour(...)
plt.tricontourf(...)
지리 좌표, 물리 시뮬레이션, 비정형 메시 데이터 같은 특별한 상황에서 유용하다.
일반 EDA 입문 단계에서는 선·막대·산점도·히스토그램·박스플롯을 먼저 익히는 것이 우선이다.
fig, ax = plt.subplots()
ax.plot(
days,
users,
)
fig.savefig(
"daily-users.png",
dpi=150,
bbox_inches="tight",
)
plt.show() 전에 저장하는 흐름이 이해하기 쉽다.
숫자처럼 보이는 문자열:
"100"
"200"
"300"
먼저 숫자로 변환해야 한다.
df["amount"] = pd.to_numeric(
df["amount"],
errors="coerce",
)
날짜는 datetime으로 변환하고 정렬한다.
df["date"] = pd.to_datetime(
df["date"]
)
df = df.sort_values(
"date"
)
색상, 마커, 라벨을 과도하게 넣으면 분석 대상보다 장식이 더 눈에 띌 수 있다.
시각화의 목표는 데이터를 더 쉽게 이해하는 것이다.
평균 막대 하나만 보면 분포와 이상치를 알 수 없다.
가능하다면 다음을 함께 고려한다.
데이터를 받으면 다음 순서로 시각화해볼 수 있다.
sns.histplot(
data=df,
x="session_time",
)
sns.boxplot(
data=df,
x="channel",
y="session_time",
)
sns.scatterplot(
data=numeric_df,
x="clicks",
y="orders",
)
ax.plot(
traffic.index,
traffic.values,
)
이 정도만 익혀도 탐색적 데이터 분석에서 필요한 기본적인 질문을 상당 부분 확인할 수 있다.
Figure와 Axes 구조를 이해하면 복잡한 그래프를 다루기 쉬워진다.histplot, boxplot, violinplot, scatterplot을 익히면 기본적인 EDA에 충분히 활용할 수 있다.plot() 메서드는 분석 결과를 빠르게 시각화할 때 편리하다.