오늘의 학습 요약
EDA의 표준 흐름인 데이터 로드, 구조 파악, 기초 통계량 확인, 결측·중복 점검, 변수별 분포 분석, 변수 간 관계 분석, 상관관계 분석 순서를 타이타닉 데이터셋에 적용하였다. 목표 변수는 생존 여부(survived)로 설정하고 성별, 객실 등급, 승선 항구, 나이, 요금 등의 변수를 중심으로 분석을 진행하였다.
분석 도구는 pandas의 describe, value_counts, groupby, crosstab과 seaborn의 countplot, histplot, boxplot, heatmap을 조합하였다. 이어서 sibsp, parch를 합산한 family_size, 15세 이하 여부를 나타내는 is_child, pd.cut으로 구간화한 age_group 파생변수를 생성하고 그룹별 생존율을 확인하였다. 마지막으로 범주형 변수를 map과 pd.get_dummies로 수치화한 뒤 상관관계 히트맵으로 시각화하였다.
0.타이타닉 탑승객 데이터 탐색적 데이터 분석(EDA)
타이타닉 탑승객 데이터를 활용한 탐색적 데이터 분석( Exploratory Data Analysis, EDA) 의 전체 과정을 학습하는 시간을 가졌다.
오늘의 학습의 목표는 이렇게 된다.
- 데이터 크기, 컬럼, 자료형을 확인
- 기초 통계량과 범주별 빈도 확인
- 결측치와 중복 데이터를 탐색
- 범주형 변수와 수치형 변수를 구분하여 분석
groupby(),crosstab(),pivot_table()을 활용- 분석 결괄를 근거로 데이터 특징 설명
1. EDA 개념과 표준 절차
EDA는 본격적인 분석이나 머신러닝 이전 단계에서 데이터를 살펴보는 과정이다. 일반적으로 다음 8단계 순서를 따른다.
- 데이터 불러오기
- 데이터 구조 확인
- 기초 통계량 확인
- 결측치와 중복 데이터 확인
- 변수별 분포 분석
- 변수 간 관계 분석
- 상관관계 분석
- 분석 결과 정리
- EDA가 시사하는 점이 뭘까?
- EDA는 단순한 사전 확인이 아니라 파이프라인의 품질을 좌우하는 단계라 볼 수 있다. EDA에서 확인한 결측 패턴,범주 분포, 상관관계는 전처리 로직에 근거가 된다.
2. 데이터 로드와 초기 설정
koreanize-matplotlib 패키지로 한글 폰트 문제를 해결하고, 실수 출력 자릿수와 기본 그래프 크기를 사전에 지정하였다. 원본 훼손을 방지하기 위해 df.copy()로 복사본을 만들어 titanic_df로 사용하였다.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import koreanize_matplotlib
plt.rcParams['figure.figsize'] = (8, 5)
pd.options.display.float_format = '{:.3f}'.format
df = sns.load_dataset('titanic')
titanic_df = df.copy()
컬럼 설명
| 컬럼명 | 설명 |
|---|---|
| survived | 생존 여부 (0 = 사망, 1 = 생존) |
| pclass | 객실 등급 (1 = 1등석, 2 = 2등석, 3 = 3등석) |
| sex | 성별 (male, female) |
| age | 나이 |
| sibsp | 함께 탑승한 형제·자매 및 배우자 수 |
| parch | 함께 탑승한 부모 및 자녀 수 |
| fare | 승선 요금 |
| embarked | 승선 항구 코드 (C, Q, S) |
| class | 객실 등급 (First, Second, Third) |
| who | 승객 구분 (man, woman, child) |
| adult_male | 성인 남성 여부 (True / False) |
| deck | 객실이 위치한 갑판(A~G), 결측치 포함 |
| embark_town | 승선 도시 (Cherbourg, Queenstown, Southampton) |
| alive | 생존 여부 (yes / no) |
| alone | 혼자 탑승 여부 (True / False) |
| --- |
3. 기초 통계량 확인
수치형 컬럼만 대상으로 하는 기본 describe()와 달리, include='all'을 지정하면 범주형 변수까지 포함한 통계량을 볼 수 있다. nunique()로 컬럼별 고유값 개수도 함께 확인한다.
titanic_df.describe(include='all')
titanic_df.nunique()
통계량 점검 시 확인해야 할 요소는 평균과 중앙값의 격차(불균형), 최솟값·최댓값의 편차(범위), 데이터 개수가 전체 행 수보다 적은 컬럼(결측), 범주형 변수의 최빈값이다.
4. 데이터 품질 확인
결측치와 중복 데이터를 각각 isna().sum(), duplicated().sum()으로 파악한다.
titanic_df.isna().sum()
print('중복 행 개수: ', titanic_df.duplicated().sum())
결측치가 확인되어도 무조건 삭제하지 않으며, 재수집 또는 파생변수로 채워 활용하는 것을 우선한다. 타이타닉 데이터는 이름·승객 번호가 포함되지 않으므로 다른 승객의 값이 우연히 동일할 수 있어 단순 중복 제거도 지양한다.
5. 목표 변수 분석: 생존 여부
value_counts에 normalize=True를 지정하면 인원수 대신 비율(0~1)이 반환되며, 여기에 100을 곱해 백분율로 변환한다.
titanic_df['survived'].value_counts(normalize=True) * 100
시각화는 sns.countplot으로 인원수를, 파이차트로 비율을 확인하였다.

6. 범주형 변수 분포
성별의 경우 인원수와 비율을 하나의 DataFrame으로 묶어 정리하였다. 승선 항구는 결측 포함 빈도를 함께 보기 위해 dropna=False를 사용한다.
sex_table = pd.DataFrame({
'인원수': titanic_df['sex'].value_counts(),
'비율(%)': titanic_df['sex'].value_counts(normalize=True) * 100
})
titanic_df['embark_town'].value_counts(dropna=False)
7. 수치형 변수 분포
histplot에
sns.histplot(data=titanic_df, x='age', bins=20, kde=True)
sns.boxplot(data=titanic_df, x='fare')
fare는 오른쪽으로 긴 꼬리를 가진 분포로 확인되어, 평균만으로는 전체 승객의 요금 특성을 설명하기 어렵다.

8. 범주형 변수와 생존 여부의 관계 "pd.crosstab()"
두 개 이상의 범주형 변수의 교차 빈도를 확인할 때 pd.crosstab()을 사용한다. 그룹별 탑승자 수, 생존자 수, 생존율은 groupby와 agg(['count', 'sum', 'mean'])로 한 번에 산출한다.
#1
pd.crosstab(titanic_df['sex'], titanic_df['survived'])
#2
survived_df = titanic_df.groupby('sex')['survived'].agg(['count', 'sum', 'mean'])
survived_df.columns = ['탑승자 수', '생존자 수', '생존율']
survived_df['생존율'] = survived_df['생존율'] * 100
동일한 방식으로 pclass, embark_town에 대해서도 class_survived_df, embark_survived_df를 생성하였다. survived가 0/1 이진값이므로 sum은 생존자 수, mean은 생존율에 대응된다는 점이 핵심이다.


9. 파생변수 생성
수치형 변수를 범주형으로 재가공하여 분석 정확도를 높이는 단계이다. 세 종류의 파생변수를 생성하였다.
| 파생변수 | 정의 | 생성 방식 |
|---|---|---|
family_size |
본인 포함 동승 가족 수 | sibsp + parch + 1 |
is_child |
15세 이하 여부 | age <= 15 불리언 |
age_group |
연령대 구간 | pd.cut 5구간 |
titanic_df['family_size'] = titanic_df['sibsp'] + titanic_df['parch'] + 1
titanic_df['is_child'] = titanic_df['age'] <= 15
titanic_df['age_group'] = pd.cut(
titanic_df['age'],
bins=[0, 15, 30, 45, 60, np.inf],
labels=['15세 이하', '16~30세', '31~45세', '46~60세', '60세 이상']
)
pd.cut은 bins로 경계값을, labels로 각 구간의 이름을 지정한다. 상한을 np.inf로 지정하면 최댓값에 관계없이 마지막 구간이 열려 있는 형태로 처리된다.
파생변수별 생존율은 앞선 groupby 패턴을 그대로 재사용하여 family_size_survived_df, age_group_survived_df로 산출하였다.
10. 상관관계 분석
수치형 변수만 선별한 후 corr()로 피어슨 상관계수 행렬을 계산하고 heatmap으로 시각화하였다.corr()메서드는 데이터프레임의 수치형 변수들 간의 상관관계를 계산하는 메서드이며, 상관관계는 두 변수 사이의 관계가 강한지를 나타낸다.
numberic_columns = ['survived', 'pclass', 'age', 'sibsp', 'parch', 'fare', 'family_size']
corr_df = titanic_df[numberic_columns].corr()
sns.heatmap(
data=corr_df,
annot=True,
fmt='.2f',
cmap='coolwarm',
center=0,
linewidths=0.5,
)

상관계수 해석 기준은 다음과 같다.
| 상관계수 범위 | 의미 |
|---|---|
| 1.0 | 완전한 양의 상관관계 |
| 0.7 ~ 1.0 | 매우 강한 양의 상관관계 |
| 0.3 ~ 0.7 | 보통의 양의 상관관계 |
| -0.3 ~ 0.3 | 거의 관계 없음 |
| -0.3 ~ -0.7 | 보통의 음의 상관관계 |
| -0.7 ~ -1.0 | 매우 강한 음의 상관관계 |
| -1.0 | 완전한 음의 상관관계 |
상관관계는 인과관계를 의미하지 않는다. survived 기준으로 pclass는 음의 상관관계, fare는 양의 상관관계를 보였다.
11. 범주형 변수를 포함한 상관관계 재분석
범주형 변수는 상관계수 계산 대상에서 제외되므로 수치화가 필요하다. 이진 범주는 map, 다중 범주는 pd.get_dummies로 원-핫 인코딩한다.
corr_df = titanic_df[[
'survived', 'sex', 'pclass', 'embarked', 'fare', 'family_size', 'age'
]]
corr_df['sex'] = corr_df['sex'].map({'male': 0, 'female': 1})
corr_df = pd.get_dummies(
corr_df,
columns=['embarked'],
dtype=int
)
corr_df = corr_df.corr()
get_dummies의 dtype=int 옵션을 지정하면 True/False가 아닌 1/0 정수로 인코딩되어 이후 상관계수 계산에 그대로 사용할 수 있다.
오늘의 핵심 포인트
- EDA는 데이터 로드 → 구조·통계·품질 확인 → 분포 → 관계 → 상관관계의 8단계 표준 절차를 따른다.
describe(include='all')은 범주형 컬럼까지 포함한 통계량을,nunique()는 컬럼별 고유값 개수를 반환한다.value_counts의normalize=True는 비율을,dropna=False는 결측 포함 빈도를 산출한다.- 이진 목표 변수에 대해
groupby(...).agg(['count', 'sum', 'mean'])을 적용하면 탑승자 수·생존자 수·생존율을 한 번에 얻는다. pd.cut은bins와labels로 수치형 변수를 명명된 범주 구간으로 변환하며,np.inf로 개방 구간을 지정한다.- 결측·중복 데이터는 즉시 삭제하지 않고 데이터 특성(재수집 가능성, 식별자 부재 등)을 근거로 처리 방침을 결정한다.
corr()는 수치형 변수만 대상으로 하므로 범주형 변수는map또는pd.get_dummies(dtype=int)로 사전 변환이 필요하다.- 상관관계와 인과관계는 구분되며, 히트맵 해석은 상관계수 구간표를 기준으로 강도와 방향을 판단한다.
'MLOps엔지니어' 카테고리의 다른 글
| ABC 부트캠프 AI파일럿 1기 MLOps 5일차_주민등록 인구통계 CSV 전처리와 plotly 시각화 (0) | 2026.08.02 |
|---|---|
| ABC 부트캠프 AI파일럿 1기 MLOps 4일차_NumPy 배열 연산과 pandas 데이터 파악하기 (0) | 2026.08.02 |
| ABC 부트캠프 AI파일럿 1기 MLOps 3일차_서울 기온 CSV 데이터 분석과 matplotlib 시각화 (0) | 2026.08.01 |
| ABC 부트캠프 AI파일럿 1기 MLOps 2일차_ 데이터 분석을 위한 파이썬 기초 (1) | 2026.07.26 |
| ABC 부트캠프 AI파일럿 1기 MLOps 1일차 (0) | 2026.07.26 |