Guider/AI/AiDevGuide0003
AI#03

AiDevGuide0003

데이터 다루기 완전 정복

AI DEV GUIDE SERIES — Step 03

📊 데이터 다루기 완전 정복 A-Z

NumPy 행렬 연산 · Pandas 데이터프레임 · Matplotlib 시각화 · EDA 현업 실전
비전공자도 데이터 과학자처럼 분석하는 완전 마스터

📚 대상: Python 기초 완료자⏱ 학습 기간: 2~3주📊 난이도: ★★★☆☆

🗺️ 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에 바로 넣을 수 있습니다 💪

10 Chapters 완료면접 Q&A TOP 10타이타닉 실전 EDA

🚀 다음 단계: AiDevGuide0004

Scikit-learn으로 머신러닝 완전 정복 시작!

반응형