전처리(Data Preprocessing)는 데이터를 분석이나 머신러닝 모델이 사용할 수 있는 형태로 정리하고 변환하는 과정이다.
- 데이터 분석 과정에서는 모델링보다 전처리에 많은 시간이 소요된다. (약 80%정도)
- 모델링은 전처리를 마친 데이터를 바탕으로 진행한다.

수집한 데이터는 대부분 문제가 있는 상태이다.
| 고객명 | 나이 | 성별 | 구매금액 | 지역 |
|---|---|---|---|---|
| 김철수 | 20 | 남 | "50000" | 서울 |
| 이영희 | 여 | "70000" | 서울시 | |
| 박민수 | 999 | M | 30000 | Seoul |
| 김철수 | 20 | 남 | "50000" | 서울 |
"50000"은 문자형 데이터| 문제 | 처리 방법 |
|---|---|
| 나이 없음 | 평균값으로 대체 |
| 나이 999 | 제거 |
| 문자형 구매금액 | 숫자형으로 변환 |
| 지역명 불일치 | 하나의 형태로 통일 |
| 중복 데이터 | 삭제 |
| 고객명 | 나이 | 성별 | 구매금액 | 지역 |
|---|---|---|---|---|
| 김철수 | 20 | 남 | 50000 | 서울 |
| 이영희 | 25 | 여 | 70000 | 서울 |
df.isnull().sum() : 컬럼별 결측치 개수 확인한다.fillna(값) : 결측치를 지정한 값으로 대체한다.mode() : 가장 자주 나타나는 값인 최빈값을 반환한다.df.describe() : 최솟값과 최댓값 등으로 이상치의 단서를 확인한다.bar : 막대그래프로 범주별 값을 비교한다. (값 비교)line : 꺽은선그래프로 시간에 따른 변화를 확인한다. (변화 추이)scatter : 산점도로 두 값의 관계를 확인한다. (변수 관계)hist : 히스토그램으로 값의 분포를 확인한다. (데이터 분포)파이썬에서 가장 널리 사용되는 데이터 시각화 라이브러리이다.
Numpy를 기반으로 해 다양한 형태의 차트와 그래프를 생성할 수 있게 해준다.
pip install matplotlib
pip install seaborn
# plt는 matplotlib.pyplot의 별칭(alias)
import platform
# 시각화를 위한 필수 4가지
import numpy as np # 수치 계산
import pandas as pd # 표 데이터
import matplotlib.pyplot as plt # 그래프 그리기 (기본)
import seaborn as sns # 그래프 그리기 (통계 전문)
# 운영체제에 맞는 한글 폰트 설정
if platform.system() == 'Windows':
plt.rcParams['font.family'] = 'D2coding' # 윈도우: D2coding
elif platform.system() == 'Darwin':
plt.rcParams['font.family'] = 'AppleGothic' # 맥
else:
plt.rcParams['font.family'] = 'NanumGothic' # 리눅스 / 코랩
plt.rcParams['axes.unicode_minus'] = False # 음수 부호 깨짐 방지
plt.rcParams['figure.figsize'] = (8, 5) # 기본 그림 크기
x 축 의 순서를 가진 값이다. (시간, 나이, 온도 등등)# 기본 선 그래프
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
y = np.array([220, 250, 230, 280, 260, 290, 270, 310, 290, 320, 330, 350])
plt.plot(x, y)
# 선 그래프를 커스터마이징 하고싶다면
# plt.plot(x, y, color='red', linestyle='--', linewidth=2, marker='o')
plt.title("월별 매출 추이")
plt.xlabel("월")
plt.ylabel("매출 (만원)")
plt.show()

# 여러 함수를 한 번에 그리기
# x = np.linspace(0, 2*np.pi, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.sin(x * 5)
# print(y1)
# print(y2)
plt.plot(x, y1, label='sin(x)', color='blue')
plt.plot(x, y2, label='cos(x)', color='red')
plt.plot(x, y3, label='cos(x)', color='green')
plt.title("여러개의 그래프")
plt.xlabel("x")
plt.ylabel("y")
plt.legend() # 범례 표시 (blue: sin, red: cos [box])
plt.grid(alpha=0.2)
plt.show()

# titanic 좌석 등급별 생존율
df = pd.read_csv('titanic.csv')
등급별_생존율 = df.groupby('pclass')['survived'].mean()
print(등급별_생존율)
plt.bar(등급별_생존율.index, 등급별_생존율.values)
plt.title('좌석 등급별 생존율')
plt.xlabel('좌석 등급') # x 축
plt.ylabel('생존율') # y 축
plt.xticks([1, 2, 3]) # 1,2,3 등급만 눈금으로
plt.show()

→ 1등급 좌석의 생존률이 높다.
plt.scatter(df['age'], df['fare'], alpha=0.5) # alpha=0.5 : 반투명. 점이 겹칠 때 필수, 겹친 곳이 진해져서 밀집도가 보임
plt.title('나이와 요금의 관계')
plt.xlabel('나이')
plt.ylabel('요금')
plt.show()

→ 젊고 요금이 싸게 탄 승객이 많다.
# bins=20 : 나이를 20개 구간으로 쪼개서 각 구간에 몇 명인지 카운팅
# edgecolor='black' : 막대 테두리 (없으면 막대가 붙어 보여서 읽기 힘듦)
# .dropna() : 결측치를 명시적으로 제외
# plt.hist()는 NaN을 자동으로 무시하므로 필수는 아님
plt.hist(df['age'].dropna(), bins=20, edgecolor='black')
plt.title('승객 나이 분포')
plt.xlabel('나이')
plt.ylabel('사람 수')
plt.show()

→ 20/30대가 가장 많이 탔다.
# 2x2 서브플롯 생성
fig, axes = plt.subplots(2, 2, figsize=(12, 8)) # 2행 2열
# 각 서브플롯에 데이터 그리기
# [0,0] 등급별 생존율
# 막대 그래프
등급 = df.groupby('pclass')['survived'].mean()
axes[0, 0].bar(등급.index, 등급.values)
axes[0, 0].set_title('등급별 생존율')
# [0,1] 성별 생존율
# 막대 그래프
성별 = df.groupby('sex')['survived'].mean()
axes[0, 1].bar(성별.index, 성별.values, color='coral')
axes[0, 1].set_title('성별 생존율')
# [1,0] 나이 분포
# 히스토그램
axes[1, 0].hist(df['age'].dropna(), bins=20, edgecolor='black')
axes[1, 0].set_title('나이 분포')
# [1,1] 나이 vs 요금
# 산점도 그래프
axes[1, 1].scatter(df['age'], df['fare'], alpha=0.4)
axes[1, 1].set_title('나이 vs 요금')
plt.tight_layout() # 서브플롯 간격 자동 조정
plt.show()

→ 2행 2열로 서브플롯 생성
# Matplotlib : 내가 직접 집계해서 넘겨야 함
등급 = df.groupby('pclass')['survived'].mean()
plt.bar(등급.index, 등급.values)
# Seaborn : 집계를 알아서 해줌
sns.barplot(data=df, x='pclass', y='survived')
sns.countplot(data=df, x='survived')
plt.title('생존자 / 사망자 수')
plt.xticks([0, 1], ['사망(0)', '생존(1)'])
plt.show()

sns.barplot(data=df, x='pclass', y='survived')
plt.title('등급별 생존율')
plt.ylabel('생존율')
plt.show()

| 함수 | counting하는 것 | y축 지정 |
|---|---|---|
countplot() | 범주별 데이터의 개수(빈도) | 개수를 직접 세는 그래프이므로 y를 지정하지 않음 |
barplot() | 범주별 평균값 또는 지정한 통계값 | 숫자 데이터를 집계하므로 y에 숫자형 컬럼을 지정 |
# 범주형 변수인 성별이나 승선 도시는 이 상관행렬에 직접 포함되지 않음
# 이러한 변수는 앞에서 사용한 그룹별 생존율이나 교차표로 분석하는 것이 적절함
# sex 성별 추가 불가능 ::> 문자열
# 숫자로 바꿔서 heatmap 추가
# df_corr = df.copy()
# df_corr["sex"] = df_corr["sex"].map({
# "male": 0,
# "female": 1
# })
# corr = df_corr.corr(numeric_only=True)
corr = df.corr(numeric_only=True)
corr.round(2)
# np.triu()는 행렬의 상삼각(Upper Triangle) 부분만 남기고 아래쪽 값을 0으로 만드는 함수
# mask = np.triu(np.ones_like(corr, dtype=bool))
plt.figure(figsize=(9, 6))
sns.heatmap(
corr,
# mask=mask,
annot=True, # 칸 안에 숫자 표시
fmt=".2f", # 소수점 2자리
cmap="coolwarm",# 색 팔레트 (파랑↔빨강)
vmin=-1,
vmax=1,
center=0, # 0을 색의 중앙(흰색)으로
linewidths=0.5) # 칸 사이 선
plt.title("상관계수 히트맵")
plt.show()

pclass와 fare는 서로 반대로 움직이는 경향이 있다. → 음의 상관관계sibsp와 parch는 모두 가족 구성원 수와 관련된 변수이므로 함께 증가하는 경향이 있다. → 양의 상관관계survived는 특히 fare와 pclass와의 상관관계가 비교적 크게 나타나는 것을 히트맵에서 확인할 수 있다.sex를 여성은 1, 남성은 0으로 변환한 경우:sex와 survived의 상관계수가 양수이면 여성이 생존과 더 관련 있다는 의미이다.# 기본
sns.histplot(data=df, x='age', bins=20)
plt.title('나이 분포')
plt.show()
# KDE 곡선 (데이터 분포를 부드럽게 추정한 밀도 곡선) 추가
# kde=True를 설정하면 히스토그램 막대 위에 데이터 분포를 부드러운 곡선으로 추정하여 나타내는 KDE 곡선이 추가됨
sns.histplot(data=df, x='age', bins=20, kde=True)
plt.title('나이 분포 + 분포 곡선')
plt.show()
# 그룹별로 나눠 보기
# hue 파라미터를 사용하면 범주형 변수에 따라 데이터를 그룹화하고, 각 그룹별 분포를 하나의 플롯에 표시할 수 있음
# hue='survived' 한 줄이면 데이터를 생존/사망으로 나눠서 색만 다르게 겹쳐 그림
sns.histplot(data=df, x='age', bins=20, hue='survived')
plt.title('생존 여부별 나이 분포')
plt.show()



scatterplot() 함수는 산점도를 그리는데 사용한다.sns.scatterplot(data=df, x='age', y='fare', hue='survived', alpha=0.6)
plt.title('나이·요금과 생존 여부')
plt.show()
# 추세선을 같이 보려면 regplot()
sns.regplot(data=df, x='age', y='fare', color='red', scatter_kws={'alpha': 0.4})
plt.title('나이와 요금 (추세선 포함)')
plt.show()


수집한 데이터가 들어왔을 때 이를 다양한 각도에서 관찰하고 이해하는 과정이다.
문제 정의 및 목표 설정
모듈 import
from IPython.display import Image
import numpy as np
import pandas as pd
import seaborn as sns
데이터셋 로드
df = sns.load_dataset("titanic")
df.head()
# 데이터 컬럼 확인
기본 데이터 조회
탐색적 데이터 분석 (EDA)
전처리
Matplotlib은 그래프를 세밀하게 직접 설정할 때 사용한다.Seaborn은 통계 그래프를 더 간단하게 그릴 때 사용한다.countplot()은 개수, barplot()은 평균값을 나타낸다.histplot()은 분포, scatterplot()은 변수 관계, heatmap()은 상관관계를 확인할 때 사용한다.EDA는 데이터를 여러 각도에서 살펴보고 특징과 패턴을 찾는 과정이다.