📊 데이터 다루기 완전 정복 A-Z
NumPy 행렬 연산 · Pandas 데이터프레임 · Matplotlib 시각화 · EDA 현업 실전
비전공자도 데이터 과학자처럼 분석하는 완전 마스터
🗺️ AI Dev Guide 시리즈 전체 흐름
| 가이드 | 주제 | 상태 |
|---|---|---|
| Guide0001 | AI 개념 완전 정복 | ✅ 완료 |
| Guide0002 | Python 기초 완전 정복 | ✅ 완료 |
| Guide0003 | 🔥 데이터 다루기 완전 정복 (현재) | 📖 학습 중 |
| Guide0004 | 머신러닝 (Scikit-learn) | ⏳ 예정 |
| Guide0005 | 딥러닝 (TensorFlow·PyTorch) | ⏳ 예정 |
| Guide0006 | 생성형 AI (OpenAI API·LangChain·RAG) | ⏳ 예정 |
| Guide0007 | 실전 프로젝트 (HuggingFace·배포) | ⏳ 예정 |
📋 전체 학습 목차
| 챕터 | 주제 | 핵심 내용 | 난이도 |
|---|---|---|---|
| 01 | 데이터 분석 생태계 개요 | NumPy·Pandas·Matplotlib 관계, 설치 | ★☆☆☆☆ |
| 02 | NumPy 배열과 행렬 연산 | ndarray, shape, reshape, 브로드캐스팅 | ★★★☆☆ |
| 03 | NumPy 고급 연산 | 인덱싱, 슬라이싱, 통계, 선형대수 | ★★★☆☆ |
| 04 | Pandas 기초 — DataFrame 완전 정복 | Series, DataFrame, read_csv, info, describe | ★★★☆☆ |
| 05 | Pandas 데이터 처리 | 결측값, 필터링, 정렬, 그룹화, merge | ★★★★☆ |
| 06 | Matplotlib 시각화 기초 | 선 그래프, 막대, 히스토그램, 산점도 | ★★★☆☆ |
| 07 | Seaborn 고급 시각화 | heatmap, pairplot, boxplot, violinplot | ★★★☆☆ |
| 08 | EDA 탐색적 데이터 분석 | 분포 확인, 이상치, 상관관계, 전처리 | ★★★★☆ |
| 09 | 실전 데이터 전처리 파이프라인 | Kaggle 타이타닉 EDA 완전 실습 | ★★★★☆ |
| 10 | 현업 면접 Q&A TOP 10 | 면접 빈출 질문과 모범 답변 | ★★★★☆ |
🌐 Chapter 01. 데이터 분석 생태계 — 왜 배워야 하나?
NumPy, Pandas, Matplotlib의 관계와 설치 — AI 데이터 처리의 첫걸음
💡 AI 개발에서 데이터 분석이 중요한 이유
AI 모델은 쓰레기 데이터 IN → 쓰레기 결과 OUT(GIGO: Garbage In, Garbage Out)이라는 원칙이 있습니다. 아무리 좋은 모델 아키텍처도 데이터가 잘못 정제되면 쓸모없습니다. 현업 데이터 과학자들은 전체 업무 시간의 60~80%를 데이터 수집·정제·분석에 씁니다.
NumPy
수치 연산 엔진
행렬·벡터·다차원 배열
AI 텐서의 기반
Pandas
데이터프레임 도구
CSV·Excel·DB 처리
데이터 정제·변환
Matplotlib
데이터 시각화
그래프·차트·플롯
인사이트 발견
⚙️ 설치 및 환경 세팅
| 라이브러리 | 설치 명령어 | 버전 확인 | 용도 |
|---|---|---|---|
| NumPy | pip install numpy |
np.__version__ |
수치 연산, 행렬 |
| Pandas | pip install pandas |
pd.__version__ |
데이터 처리 |
| Matplotlib | pip install matplotlib |
plt.__version__ |
기본 시각화 |
| Seaborn | pip install seaborn |
sns.__version__ |
고급 시각화 |
| 한번에 설치 | pip install numpy pandas matplotlib seaborn scipy |
||
# ===== 표준 임포트 (현업에서 항상 이렇게 씁니다) =====
import numpy as np # np로 줄여 쓰는 것이 표준
import pandas as pd # pd로 줄여 쓰는 것이 표준
import matplotlib.pyplot as plt # plt로 줄여 쓰는 것이 표준
import seaborn as sns # sns로 줄여 쓰는 것이 표준
# Jupyter/Colab 그래프 인라인 표시
%matplotlib inline
# 버전 확인
print(f"NumPy: {np.__version__}")
print(f"Pandas: {pd.__version__}")
print(f"Matplotlib: {plt.matplotlib.__version__}")
print(f"Seaborn: {sns.__version__}")
🔢 Chapter 02. NumPy 배열과 행렬 연산 완전 정복
ndarray, shape, dtype, reshape, 브로드캐스팅 — AI 텐서 연산의 핵심
💡 NumPy란? Python list와 무엇이 다른가?
NumPy는 Numerical Python의 약자로, 대규모 수치 연산에 특화된 라이브러리입니다. Python의 list는 여러 타입을 담을 수 있지만 속도가 느립니다. NumPy의 ndarray는 동일한 타입의 원소를 C언어 수준의 속도로 처리합니다. AI에서 이미지는 픽셀 배열, 모델 가중치는 행렬, 배치 데이터는 3차원 이상의 텐서로 모두 NumPy로 표현됩니다.
import numpy as np
# ===== ndarray 생성 기본 =====
a = np.array([1, 2, 3, 4, 5]) # 1차원 배열 (벡터)
b = np.array([[1,2,3],[4,5,6]]) # 2차원 배열 (행렬)
c = np.array([[[1,2],[3,4]],[[5,6],[7,8]]]) # 3차원 (배치+높이+너비)
# 핵심 속성
print(b.shape) # (2, 3) — 2행 3열
print(b.ndim) # 2 — 차원 수
print(b.dtype) # int64 — 데이터 타입
print(b.size) # 6 — 전체 원소 수
# ===== 자주 쓰는 배열 생성 함수 =====
zeros = np.zeros((3, 4)) # 3x4 영행렬 (모델 초기화)
ones = np.ones((2, 3)) # 2x3 전부 1
eye = np.eye(4) # 4x4 단위행렬
rng = np.random.randn(100, 10) # 100x10 정규분포 난수 (가중치 초기화)
arange = np.arange(0, 10, 2) # [0, 2, 4, 6, 8]
linspace = np.linspace(0, 1, 5) # [0.0, 0.25, 0.5, 0.75, 1.0] — 학습률 탐색
# ===== reshape — 형태 변환 (AI 핵심!) =====
flat = np.arange(1, 13) # [1,2,3,...,12] — 1차원 12개
matrix = flat.reshape(3, 4) # 3행 4열 행렬
tensor = flat.reshape(2, 2, 3) # 2x2x3 3차원 텐서
back = matrix.reshape(-1) # -1: 자동 계산으로 1차원 복원
# 이미지 전처리 예시: (H,W,C) → (C,H,W) — PyTorch 형식
img_hwc = np.random.randint(0, 256, (224, 224, 3)) # HWC (일반 이미지)
img_chw = img_hwc.transpose(2, 0, 1) # CHW (PyTorch Tensor 형식)
print(img_hwc.shape) # (224, 224, 3)
print(img_chw.shape) # (3, 224, 224)
⚡ 브로드캐스팅 — NumPy 마법의 핵심
브로드캐스팅은 크기가 다른 배열끼리 연산할 때 자동으로 형태를 맞춰주는 기능입니다. 이 덕분에 반복문 없이 대용량 배열 연산을 단 한 줄로 처리할 수 있습니다.
# ===== 브로드캐스팅 =====
a = np.array([[1,2,3],[4,5,6]]) # shape (2, 3)
b = np.array([10, 20, 30]) # shape (3,) → (1, 3)로 자동 확장
result = a + b # [[11,22,33],[14,25,36]] — 각 행에 b 더해짐
# AI 실전 활용: 이미지 정규화 (픽셀값 0~255 → 0~1)
images = np.random.randint(0, 256, (100, 224, 224, 3)) # 100장 이미지
mean = np.array([0.485, 0.456, 0.406]) # ImageNet 평균값 (채널별)
std = np.array([0.229, 0.224, 0.225]) # ImageNet 표준편차
normalized = (images / 255.0 - mean) / std # 브로드캐스팅으로 100장 동시 정규화!
print(normalized.shape) # (100, 224, 224, 3) — 그대로
# ===== 기본 수학 연산 =====
x = np.array([1.0, 2.0, 3.0, 4.0])
print(x + 1) # [2. 3. 4. 5.]
print(x * 2) # [2. 4. 6. 8.]
print(x ** 2) # [1. 4. 9. 16.] — 각 원소 제곱
print(np.sqrt(x)) # [1. 1.41 1.73 2.] — 제곱근
print(np.exp(x)) # 지수 함수 (softmax 계산에 사용)
print(np.log(x)) # 자연로그 (cross-entropy 손실)
🧮 Chapter 03. NumPy 고급 — 인덱싱·통계·선형대수
팬시 인덱싱, 불리언 마스킹, 행렬 곱, 고유값 — 현업 AI 필수 연산
🎯 인덱싱과 슬라이싱
import numpy as np
arr = np.array([[10,20,30],
[40,50,60],
[70,80,90]])
# 기본 인덱싱
print(arr[0, 1]) # 20 (0행 1열)
print(arr[1, :]) # [40, 50, 60] (1행 전체)
print(arr[:, 2]) # [30, 60, 90] (2열 전체)
print(arr[0:2, 1:3]) # [[20,30],[50,60]] (부분 행렬)
# ===== 불리언 마스킹 — AI 데이터 필터링 =====
scores = np.array([0.55, 0.92, 0.38, 0.88, 0.71, 0.95])
mask = scores >= 0.8 # [False, True, False, True, False, True]
high = scores[mask] # [0.92, 0.88, 0.95] — 조건 필터링
print(f"고신뢰도 예측: {high}")
print(f"개수: {mask.sum()}") # True 개수 = 3
# ===== 팬시 인덱싱 — 여러 인덱스 한번에 =====
labels = np.array(["cat", "dog", "bird", "fish", "cat"])
selected = labels[[0, 2, 4]] # ["cat", "bird", "cat"]
# ===== 통계 함수 =====
data = np.random.randn(1000) # 1000개 정규분포 샘플
print(f"평균: {data.mean():.4f}") # np.mean(data)와 동일
print(f"표준편차: {data.std():.4f}") # np.std(data)와 동일
print(f"최솟값: {data.min():.4f}")
print(f"최댓값: {data.max():.4f}")
print(f"중앙값: {np.median(data):.4f}")
print(f"합계: {data.sum():.4f}")
# 축(axis)별 연산 — AI 배치 처리 핵심
batch = np.random.randn(32, 128) # 32개 샘플, 128차원 특징
batch_mean = batch.mean(axis=0) # 각 특징의 평균 (shape: 128,)
sample_norm = batch.mean(axis=1) # 각 샘플의 평균 (shape: 32,)
# ===== 선형대수 — 딥러닝 순전파 핵심 =====
W = np.random.randn(128, 64) # 가중치 행렬 (128 입력 → 64 출력)
x = np.random.randn(32, 128) # 배치 입력 (32 샘플, 128 특징)
# 행렬 곱 (순전파 연산)
output = x @ W # = np.matmul(x, W) — (32, 128) @ (128, 64) = (32, 64)
print(output.shape) # (32, 64)
A = np.array([[4,2],[1,3]])
eigenvalues, eigenvectors = np.linalg.eig(A) # 고유값 분해 (PCA 핵심)
print(eigenvalues) # [5. 2.]
inv_A = np.linalg.inv(A) # 역행렬
U, S, Vt = np.linalg.svd(A) # 특이값 분해 (SVD) — 추천 시스템 기반
📋 Chapter 04. Pandas DataFrame 완전 정복
Series, DataFrame, read_csv, info, describe — AI 데이터 처리의 엑셀
💡 Pandas란? 왜 필요한가?
Pandas는 데이터를 엑셀 스프레드시트처럼 표(Table) 형태로 다루는 라이브러리입니다. AI 개발 시 CSV, Excel, DB에서 데이터를 불러와 결측값 처리, 피처 엔지니어링, 정규화 등의 전처리를 수행하는 데 없어서는 안 될 도구입니다.
| 구조 | 설명 | NumPy 비교 | 특징 |
|---|---|---|---|
| Series | 1차원 레이블 배열 | 1D ndarray + 인덱스 | 컬럼 하나, 시계열 데이터 |
| DataFrame | 2차원 테이블 | 2D ndarray + 행/열 이름 | CSV 파일, DB 테이블과 유사 |
import pandas as pd
import numpy as np
# ===== DataFrame 생성 =====
df = pd.DataFrame({
"이름": ["김철수", "이영희", "박민준", "최지수", "정우성"],
"나이": [25, 32, 28, 35, 22],
"직업": ["개발자", "디자이너", "개발자", "PM", "개발자"],
"연봉": [4500, 3800, 5200, 6000, np.nan], # NaN = 결측값
"AI경험": [True, False, True, True, False]
})
# ===== 기본 탐색 함수 (데이터 처음 받으면 이것부터!) =====
print(df.shape) # (5, 5) — 5행 5열
print(df.dtypes) # 각 컬럼 데이터 타입
df.info() # 행 수, 컬럼 수, 결측값, 메모리 사용량
df.describe() # 수치형 컬럼의 통계 요약 (count, mean, std, min, 25%, 50%, 75%, max)
df.head(3) # 처음 3행 보기
df.tail(2) # 마지막 2행 보기
df.sample(3) # 랜덤 3행 보기
# ===== 컬럼 선택 =====
name_series = df["이름"] # Series 반환
subset = df[["이름", "연봉"]] # DataFrame 반환 (2개 컬럼)
age = df["나이"].values # NumPy 배열로 변환
# ===== 행 선택 — loc (라벨), iloc (정수 인덱스) =====
first_row = df.iloc[0] # 0번째 행 (정수 인덱스)
row_0_2 = df.iloc[0:3] # 0~2행 (슬라이싱)
specific = df.loc[0, "이름"] # "김철수" (라벨 인덱스)
# ===== CSV 파일 불러오기 (실제 데이터 처리의 시작) =====
# df = pd.read_csv("data.csv", encoding="utf-8")
# df = pd.read_csv("data.csv", sep=",", header=0, index_col=0)
# df.to_csv("output.csv", index=False) # CSV 저장
# Kaggle 타이타닉 데이터 예시
# titanic = pd.read_csv("train.csv")
# titanic.head()
🔧 Chapter 05. Pandas 데이터 처리 완전 정복
결측값, 필터링, 정렬, 그룹화, merge, apply — 현업 데이터 처리의 모든 것
🩹 결측값(NaN) 처리 — AI 데이터 정제의 핵심
import pandas as pd
import numpy as np
df = pd.DataFrame({
"age": [25, np.nan, 28, 35, np.nan],
"income": [4500, 3800, np.nan, 6000, 2500],
"city": ["서울", "부산", np.nan, "서울", "대구"]
})
# 결측값 확인
print(df.isnull().sum()) # 컬럼별 결측값 수
print(df.isnull().sum() / len(df) * 100) # 결측값 비율(%)
# 방법 1: 결측값 행 삭제
df_drop = df.dropna() # 결측값 있는 행 전체 삭제
df_drop2 = df.dropna(subset=["age"]) # age만 결측값 있는 행 삭제
# 방법 2: 결측값 채우기 (더 많이 사용)
df["age"].fillna(df["age"].mean(), inplace=True) # 평균으로 대체
df["income"].fillna(df["income"].median(), inplace=True) # 중앙값으로 대체
df["city"].fillna("Unknown", inplace=True) # 문자열은 "Unknown"으로
df["age"] = df["age"].fillna(method="ffill") # 앞 값으로 채우기 (시계열)
# ===== 필터링 (조건 기반 행 선택) =====
df2 = pd.DataFrame({
"name": ["A", "B", "C", "D", "E"],
"age": [25, 32, 28, 35, 22],
"dept": ["AI", "HR", "AI", "PM", "AI"],
"salary": [5000, 3500, 5500, 6000, 4000]
})
ai_team = df2[df2["dept"] == "AI"] # AI 부서만
senior_ai = df2[(df2["dept"] == "AI") & (df2["age"] > 25)] # AI이면서 25세 초과
high_pay = df2[df2["salary"].between(4500, 6000)] # 급여 범위 필터
ai_or_pm = df2[df2["dept"].isin(["AI", "PM"])] # AI 또는 PM 부서
# ===== 정렬 =====
df2_sorted = df2.sort_values("salary", ascending=False) # 급여 내림차순
df2_multi = df2.sort_values(["dept", "salary"], ascending=[True, False])
# ===== 그룹화 — GroupBy (SQL GROUP BY) =====
grouped = df2.groupby("dept")["salary"]
print(grouped.mean()) # 부서별 평균 연봉
print(grouped.max()) # 부서별 최고 연봉
print(grouped.count()) # 부서별 인원 수
agg_result = df2.groupby("dept").agg({
"salary": ["mean", "max", "min"],
"age": "mean"
})
# ===== apply — 사용자 정의 함수 적용 =====
df2["salary_grade"] = df2["salary"].apply(
lambda x: "High" if x >= 5000 else ("Mid" if x >= 4000 else "Low")
)
# ===== merge — SQL JOIN =====
dept_info = pd.DataFrame({
"dept": ["AI", "HR", "PM"],
"office": ["판교", "강남", "분당"]
})
merged = pd.merge(df2, dept_info, on="dept", how="left") # LEFT JOIN
📈 Chapter 06. Matplotlib 시각화 완전 정복
선 그래프, 막대, 히스토그램, 산점도, 서브플롯 — 데이터를 눈에 보이게!
🎨 Matplotlib 핵심 구조 이해
Matplotlib은 Figure(도화지) → Axes(그래프 영역) → 데이터 계층 구조를 가집니다. 여러 그래프를 한 번에 배치하려면 subplot을 사용합니다.
import matplotlib.pyplot as plt
import numpy as np
# ===== 1. 선 그래프 — 학습 곡선 시각화 =====
epochs = list(range(1, 21))
train_loss = [1.5, 1.2, 1.0, 0.85, 0.72, 0.62, 0.54, 0.48,
0.43, 0.39, 0.35, 0.32, 0.29, 0.27, 0.25,
0.23, 0.21, 0.20, 0.19, 0.18]
val_loss = [1.6, 1.3, 1.1, 0.95, 0.82, 0.75, 0.68, 0.64,
0.61, 0.59, 0.58, 0.57, 0.57, 0.58, 0.59,
0.60, 0.62, 0.64, 0.66, 0.69]
plt.figure(figsize=(10, 5))
plt.plot(epochs, train_loss, "b-o", label="Train Loss", linewidth=2, markersize=4)
plt.plot(epochs, val_loss, "r--s", label="Val Loss", linewidth=2, markersize=4)
plt.axvline(x=12, color="g", linestyle=":", label="Early Stop") # 과적합 시작점
plt.title("학습 곡선 (Training Curve)", fontsize=14, fontweight="bold")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# ===== 2. 서브플롯 — 여러 그래프 한 번에 =====
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# 막대 그래프
categories = ["정확도", "재현율", "정밀도", "F1"]
values = [0.93, 0.91, 0.95, 0.93]
axes[0,0].bar(categories, values, color=["#3498db","#e74c3c","#2ecc71","#f39c12"])
axes[0,0].set_title("모델 성능 지표")
axes[0,0].set_ylim(0.85, 1.0)
# 히스토그램
data = np.random.normal(0.75, 0.1, 1000)
axes[0,1].hist(data, bins=30, color="#9b59b6", edgecolor="black", alpha=0.7)
axes[0,1].set_title("예측 점수 분포")
# 산점도
x = np.random.randn(200)
y = x * 0.7 + np.random.randn(200) * 0.5
axes[1,0].scatter(x, y, c="#e74c3c", alpha=0.5, s=30)
axes[1,0].set_title("실제값 vs 예측값")
# 파이 차트
class_dist = [700, 200, 100]
class_labels = ["정상", "경계", "이상"]
axes[1,1].pie(class_dist, labels=class_labels, autopct="%1.1f%%", startangle=90)
axes[1,1].set_title("클래스 분포")
plt.suptitle("AI 모델 분석 대시보드", fontsize=16, fontweight="bold")
plt.tight_layout()
plt.show()
🎨 Chapter 07. Seaborn 고급 시각화
heatmap, pairplot, boxplot, violinplot — 한 줄로 아름다운 통계 그래프
🔥 Seaborn = Matplotlib + 통계 + 아름다움
Seaborn은 Matplotlib을 기반으로 만들어진 고수준 시각화 라이브러리입니다. 통계적 시각화에 특화되어 있어 상관관계, 분포, 카테고리 비교를 한 줄로 그릴 수 있습니다. 특히 heatmap은 AI에서 상관행렬, 혼동행렬(Confusion Matrix) 시각화에 필수입니다.
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Seaborn 스타일 설정
sns.set_style("whitegrid")
sns.set_palette("husl")
# 샘플 데이터 (Seaborn 내장)
tips = sns.load_dataset("tips") # 팁 데이터셋
iris = sns.load_dataset("iris") # 붓꽃 데이터셋 (ML 입문 필수)
# ===== 1. heatmap — 상관행렬 시각화 =====
df = pd.DataFrame(np.random.randn(100, 5), columns=["A","B","C","D","E"])
corr = df.corr() # 상관계수 행렬 계산
plt.figure(figsize=(8, 6))
sns.heatmap(corr, annot=True, fmt=".2f", cmap="coolwarm",
vmin=-1, vmax=1, center=0, square=True)
plt.title("특징 상관행렬")
plt.show()
# ===== 2. pairplot — 변수 쌍 관계 한눈에 =====
sns.pairplot(iris, hue="species", diag_kind="kde")
plt.suptitle("Iris Pairplot — 클래스별 특징 관계", y=1.02)
plt.show()
# ===== 3. boxplot — 분포와 이상치 한눈에 =====
plt.figure(figsize=(8, 5))
sns.boxplot(data=tips, x="day", y="total_bill", hue="sex")
plt.title("요일별·성별 결제 금액 분포")
plt.show()
# ===== 4. 혼동행렬 heatmap (분류 모델 평가) =====
from sklearn.metrics import confusion_matrix
y_true = [0, 1, 1, 0, 1, 0, 1, 1]
y_pred = [0, 1, 0, 0, 1, 1, 1, 1]
cm = confusion_matrix(y_true, y_pred)
plt.figure(figsize=(6, 4))
sns.heatmap(cm, annot=True, fmt="d", cmap="Blues",
xticklabels=["부정","긍정"], yticklabels=["부정","긍정"])
plt.xlabel("예측")
plt.ylabel("실제")
plt.title("혼동 행렬 (Confusion Matrix)")
plt.show()
🔍 Chapter 08. EDA — 탐색적 데이터 분석 완전 정복
분포 확인, 이상치 탐지, 상관관계 분석, 피처 엔지니어링 — 현업 데이터 사이언티스트처럼
💡 EDA란? 왜 필수인가?
EDA(Exploratory Data Analysis, 탐색적 데이터 분석)는 데이터를 모델에 넣기 전 데이터의 특성, 패턴, 이상치를 파악하는 과정입니다. AI 개발에서 모델보다 데이터가 더 중요합니다. EDA를 통해 어떤 피처가 중요한지, 어떤 전처리가 필요한지를 파악합니다.
| EDA 단계 | 목적 | 주요 도구 | 핵심 질문 |
|---|---|---|---|
| 1. 데이터 개요 | 크기·타입·결측값 파악 | info(), describe() | 데이터가 몇 개? 타입은? |
| 2. 분포 확인 | 각 변수 분포 시각화 | hist, boxplot | 정규분포? 편향? |
| 3. 이상치 탐지 | 비정상 데이터 발견 | IQR, Z-score | 튀는 값이 있나? |
| 4. 상관관계 | 변수 간 관계 파악 | heatmap, pairplot | 어떤 피처가 중요? |
| 5. 피처 엔지니어링 | 새 변수 생성·변환 | apply, log, 원핫인코딩 | 어떻게 변환할까? |
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# ===== EDA 완전 흐름 (실전 템플릿) =====
# 1. 데이터 불러오기 & 기본 정보
# df = pd.read_csv("data.csv")
np.random.seed(42)
df = pd.DataFrame({
"age": np.random.randint(20, 70, 500),
"income": np.random.exponential(50000, 500), # 우편향 분포
"score": np.random.normal(70, 15, 500),
"grade": np.random.choice(["A","B","C","D"], 500, p=[0.2,0.4,0.3,0.1]),
"churn": np.random.choice([0,1], 500, p=[0.8,0.2]) # 타겟(이탈여부)
})
df.loc[10:20, "income"] = np.nan # 인위적 결측값 생성
# Step 1. 기본 정보 파악
print("==== 데이터 기본 정보 ====")
print(f"Shape: {df.shape}")
df.info()
print(df.describe())
print("\n결측값:")
print(df.isnull().sum())
# Step 2. 이상치 탐지 — IQR 방법
Q1 = df["income"].quantile(0.25)
Q3 = df["income"].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
outliers = df[(df["income"] < lower) | (df["income"] > upper)]
print(f"이상치 수: {len(outliers)}개")
# Step 3. 피처 엔지니어링
df["log_income"] = np.log1p(df["income"]) # 로그 변환 (우편향 → 정규분포)
df["age_group"] = pd.cut(df["age"],
bins=[0,30,45,60,100],
labels=["20대","30-40대","50대","60대+"])
# 원핫 인코딩 (카테고리 → 숫자)
grade_dummies = pd.get_dummies(df["grade"], prefix="grade")
df = pd.concat([df, grade_dummies], axis=1)
# Step 4. 상관관계 분석
num_cols = ["age", "income", "log_income", "score", "churn"]
corr_matrix = df[num_cols].corr()
print(corr_matrix["churn"].sort_values(ascending=False)) # 타겟과의 상관관계
🏆 Chapter 09. 실전 — Kaggle 타이타닉 EDA 완전 실습
처음부터 끝까지 완전한 EDA + 전처리 파이프라인 구현
🚢 타이타닉 데이터셋 완전 EDA
Kaggle의 가장 유명한 입문 데이터셋인 타이타닉으로 실전 EDA를 연습합니다. 이 과정을 익히면 어떤 데이터셋이든 동일한 방식으로 분석할 수 있습니다.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# ===== 1. 데이터 로드 =====
# Kaggle에서 다운로드 후: pd.read_csv("train.csv")
url = "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"
df = pd.read_csv(url)
# ===== 2. 기본 탐색 =====
print("=== Shape ===", df.shape) # (891, 12)
print("=== Columns ===", df.columns.tolist())
print("=== 결측값 ===")
print(df.isnull().sum()[df.isnull().sum() > 0])
# 컬럼 설명
# Survived: 생존여부(0=사망, 1=생존) — 타겟 변수
# Pclass: 선실 등급 (1=1등석, 2=2등석, 3=3등석)
# Sex: 성별
# Age: 나이 (177개 결측값)
# SibSp: 형제자매/배우자 수
# Parch: 부모/자녀 수
# Fare: 요금
# Embarked: 탑승 항구 (C=셰르부르, Q=퀸즈타운, S=사우샘프턴)
# ===== 3. 생존율 분석 =====
print(f"전체 생존율: {df.Survived.mean():.1%}")
print("성별 생존율:")
print(df.groupby("Sex")["Survived"].mean())
print("선실등급별 생존율:")
print(df.groupby("Pclass")["Survived"].mean())
# ===== 4. 전처리 파이프라인 =====
def preprocess_titanic(df):
"""타이타닉 데이터 전처리 파이프라인"""
df = df.copy()
# 결측값 처리
df["Age"].fillna(df["Age"].median(), inplace=True)
df["Fare"].fillna(df["Fare"].median(), inplace=True)
df["Embarked"].fillna(df["Embarked"].mode()[0], inplace=True)
# 피처 엔지니어링
df["FamilySize"] = df["SibSp"] + df["Parch"] + 1 # 가족 수
df["IsAlone"] = (df["FamilySize"] == 1).astype(int) # 혼자 탑승 여부
df["AgeGroup"] = pd.cut(df["Age"], bins=[0,12,18,35,60,100],
labels=[0,1,2,3,4]).astype(int)
df["LogFare"] = np.log1p(df["Fare"]) # 로그 변환
# 인코딩
df["Sex"] = df["Sex"].map({"male": 0, "female": 1})
embarked_dummies = pd.get_dummies(df["Embarked"], prefix="Emb")
df = pd.concat([df, embarked_dummies], axis=1)
# 불필요한 컬럼 제거
drop_cols = ["Name", "Ticket", "Cabin", "Embarked", "PassengerId"]
df.drop(columns=drop_cols, inplace=True, errors="ignore")
return df
processed_df = preprocess_titanic(df)
print("전처리 완료!")
print(processed_df.shape)
print(processed_df.dtypes)
🎯 Chapter 10. 현업 면접 질문과 답변 TOP 10
데이터 분석 면접에서 가장 자주 나오는 질문과 모범 답변
Q1. NumPy list보다 빠른 이유는?
A: NumPy 배열은 연속된 메모리 블록에 동일 타입의 데이터를 저장합니다(C 배열 기반). Python list는 각 원소가 별개의 Python 객체이고 포인터로 연결되어 있어 메모리가 흩어져 있습니다. NumPy는 ① C/포트란으로 구현된 벡터화 연산 ② BLAS/LAPACK 수학 라이브러리 활용 ③ SIMD 명령어 활용으로 list 대비 10~100배 빠릅니다. 또한 dtype을 고정해 타입 체크 오버헤드가 없습니다.
Q2. 브로드캐스팅이란 무엇이며 언제 사용하나요?
A: 브로드캐스팅은 크기가 다른 배열 간 연산 시 작은 배열을 자동으로 확장하는 NumPy 메커니즘입니다. 규칙: ① 차원 수가 다르면 앞에 1을 추가 ② 크기가 1인 축은 다른 배열의 크기로 확장. 활용: 이미지 배치 정규화(100장을 평균 벡터로 한 번에 나누기), 편향 행렬 덧셈, 거리 행렬 계산 등. for문 없이 대용량 연산을 단일 표현식으로 처리할 때 필수입니다.
Q3. Pandas에서 결측값을 처리하는 전략은?
A: ① 삭제(dropna) — 결측값 비율이 5% 미만이거나 해당 행/컬럼이 중요하지 않을 때 ② 평균/중앙값 대체 — 수치형 데이터, 이상치 없으면 평균, 있으면 중앙값 ③ 최빈값 대체 — 범주형 데이터 ④ 시계열 보간(interpolate) — 시간 순서가 있는 데이터 ⑤ 예측 모델로 대체(KNN, Regression Imputation) — 결측값이 많을 때 고급 방법. 결측값이 무작위(MAR)인지 비무작위(MNAR)인지에 따라 전략이 달라집니다.
Q4. 데이터 정규화(Normalization)와 표준화(Standardization) 차이?
A: 정규화(Min-Max Scaling): (x-min)/(max-min)으로 0~1 범위로 변환. 이상치에 민감. 신경망 입력층에서 자주 사용. 표준화(Z-score Standardization): (x-mean)/std로 평균=0, 표준편차=1 변환. 이상치에 강건. SVM, 로지스틱 회귀 등 거리 기반 모델에서 선호. 선택 기준: 데이터에 이상치가 있으면 Robust Scaler, 이상치 없고 신경망이면 정규화, 그 외 일반적으로 표준화를 사용합니다.
Q5. EDA에서 이상치를 어떻게 탐지하고 처리하나요?
A: 탐지 방법: ① IQR 방법 — Q1-1.5*IQR 미만, Q3+1.5*IQR 초과 (박스플롯) ② Z-score — |z| > 3 인 값 ③ 산점도·히스토그램 시각화. 처리 방법: ① 삭제 (데이터가 충분할 때) ② 클리핑 — 상하한으로 대체 (np.clip) ③ 로그 변환 — 우편향 분포 완화 ④ 이상치 플래그 피처 추가. 주의: 이상치가 실제 인사이트일 수 있으므로 무조건 제거하지 않고 도메인 지식으로 판단해야 합니다.
Q6. 피처 엔지니어링이란? 어떤 기법을 써봤나요?
A: 피처 엔지니어링은 원시 데이터에서 모델 성능을 높이는 새로운 특징을 만들거나 변환하는 과정입니다. 주요 기법: ① 수치 변환 — 로그(log1p), 제곱근, Box-Cox ② 구간화(Binning) — pd.cut, pd.qcut ③ 범주 인코딩 — 원핫인코딩, Label, Target Encoding ④ 상호작용 특징 — 두 컬럼 곱/나눔 ⑤ 날짜 분해 — 연/월/일/요일/시간 분리 ⑥ 집계 특징 — 그룹별 평균/최대값. 타이타닉에서 FamilySize=SibSp+Parch+1 같은 새 피처가 대표 예시입니다.
Q7. groupby와 pivot_table의 차이는?
A: groupby는 1개 이상의 컬럼을 기준으로 데이터를 묶어 집계 함수를 적용합니다. pivot_table은 groupby를 더 직관적인 크로스탭(교차표) 형태로 표현하며, 행/열/값/집계함수를 별도로 지정합니다. 예: groupby("dept")["salary"].mean()과 pivot_table(index="dept", values="salary", aggfunc="mean")은 같은 결과입니다. 두 변수 간 교차 분석(예: 성별×등급별 생존율)에는 pivot_table이 더 편리합니다.
Q8. 상관관계가 높은 피처가 많을 때 어떻게 처리하나요?
A: 다중공선성(Multicollinearity) 문제입니다. ① 하나 제거 — 상관계수 |r| > 0.9 이상인 쌍에서 타겟과 덜 관련된 것 제거 ② PCA(주성분분석) — 상관된 피처들을 독립 성분으로 변환 ③ VIF(분산팽창인수) 계산 — VIF > 10인 피처 제거 ④ L1 정규화(Lasso) — 자동으로 상관된 피처 중 하나를 0으로 수렴. 선형 모델에서는 중요하지만, 트리 기반 모델(Random Forest, XGBoost)은 다중공선성에 상대적으로 강건합니다.
Q9. 불균형 데이터셋은 어떻게 처리하나요?
A: 클래스 불균형(예: 사기탐지에서 사기 1% vs 정상 99%) 처리: ① 언더샘플링 — 다수 클래스 줄이기 (RandomUnderSampler) ② 오버샘플링 — 소수 클래스 늘리기 (SMOTE, RandomOverSampler) ③ class_weight 설정 — sklearn 모델의 class_weight="balanced" ④ 평가지표 변경 — Accuracy 대신 F1-Score, AUROC, Precision-Recall 사용 ⑤ Focal Loss — 딥러닝에서 소수 클래스에 더 높은 가중치. 실무에서는 SMOTE + class_weight 조합을 가장 많이 사용합니다.
Q10. 실제 업무에서 EDA를 어떻게 체계화하나요?
A: 현업 EDA 표준 프로세스: ① 데이터 카탈로그 작성 — 컬럼 이름·타입·설명·결측률 정리 ② 자동화 EDA 도구 — pandas-profiling(ydata-profiling), sweetviz 활용 ③ 비즈니스 질문 정의 — "어떤 고객이 이탈하나?" 같은 명확한 질문부터 ④ 가설 수립·검증 — t-test, chi-square test, ANOVA ⑤ 반복적 분석 — 피처 추가→모델 학습→성능 확인→다시 EDA 사이클. 최종적으로 EDA 결과를 팀과 공유할 수 있는 Jupyter Notebook 형태로 정리합니다.
✅ AiDevGuide0003 완료 체크리스트
📗 NumPy
- ✅ ndarray 생성·속성 이해
- ✅ reshape, transpose 활용
- ✅ 브로드캐스팅 개념 이해
- ✅ 선형대수 연산 (@, linalg)
📘 Pandas
- ✅ DataFrame 생성·탐색
- ✅ 결측값 처리 전략
- ✅ 필터링·정렬·그룹화
- ✅ merge(join) 활용
📊 시각화
- ✅ Matplotlib 기본 그래프
- ✅ 서브플롯 구성
- ✅ Seaborn heatmap, pairplot
- ✅ 혼동행렬 시각화
🔍 EDA & 전처리
- ✅ EDA 5단계 흐름 이해
- ✅ 이상치 탐지 (IQR)
- ✅ 피처 엔지니어링
- ✅ 타이타닉 전처리 파이프라인
AiDevGuide0003 완료!
데이터 분석을 완전히 정복했습니다!
이제 어떤 데이터셋도 분석하고 AI에 바로 넣을 수 있습니다 💪
🚀 다음 단계: AiDevGuide0004
Scikit-learn으로 머신러닝 완전 정복 시작!