🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

타이타닉 데이터로 배우는 파이썬 EDA 완벽 가이드 - 슬라이드 1/8
A

AI Generated

2025. 12. 17. · 6 Views

타이타닉 데이터로 배우는 파이썬 EDA 완벽 가이드

타이타닉 데이터셋으로 배우는 탐색적 데이터 분석(EDA)입니다. 데이터 로드부터 시각화까지, 실무에서 사용하는 데이터 분석 기법을 차근차근 배워봅니다. 초급 데이터 분석가를 위한 실전 예제입니다.


목차

  1. 타이타닉_데이터셋_소개
  2. 데이터_로드_및_기본_탐색
  3. 생존율_기본_통계
  4. 성별에_따른_생존율
  5. 객실_등급별_생존율
  6. 나이와_생존율_관계
  7. 상관관계_히트맵_그리기

1. 타이타닉 데이터셋 소개

어느 날 김개발 씨는 데이터 분석 부서로 첫 출근을 했습니다. 팀장님이 건넨 것은 타이타닉 데이터셋이었습니다.

"이 데이터로 먼저 분석 연습을 해보세요."

타이타닉 데이터셋은 데이터 분석을 배우는 사람들이 가장 먼저 만나는 데이터입니다. 1912년 타이타닉호 침몰 사고의 승객 정보를 담고 있습니다.

나이, 성별, 객실 등급, 생존 여부 등의 정보가 포함되어 있어 데이터 분석의 기초를 배우기에 완벽한 데이터셋입니다.

다음 코드를 살펴봅시다.

# 필요한 라이브러리 불러오기
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# 한글 폰트 설정 (그래프에서 한글 깨짐 방지)
plt.rcParams['font.family'] = 'DejaVu Sans'

# 경고 메시지 무시
import warnings
warnings.filterwarnings('ignore')

print("타이타닉 데이터 분석 준비 완료!")

김개발 씨는 컴퓨터 공학을 전공했지만 데이터 분석은 처음이었습니다. 팀장님은 친절하게 설명해주셨습니다.

"타이타닉 데이터로 시작하면 좋아요. 데이터 분석의 기본을 모두 배울 수 있거든요." 타이타닉 데이터셋은 무엇이길래 이렇게 유명할까요?

마치 요리를 배울 때 계란 프라이부터 시작하는 것과 같습니다. 너무 어렵지도 않고, 그렇다고 너무 쉽지도 않습니다.

적당한 난이도로 데이터 분석의 전체 과정을 경험할 수 있습니다. 1912년 4월 15일, 타이타닉호는 빙산과 충돌하여 침몰했습니다.

2,224명의 승객과 승무원 중 1,502명이 사망했습니다. 이 비극적인 사건의 데이터가 지금은 많은 사람들에게 데이터 분석을 가르치는 귀중한 자료가 되었습니다.

데이터셋에는 어떤 정보가 들어있을까요? 승객의 나이, 성별, 객실 등급, 승선 항구, 요금, 그리고 가장 중요한 생존 여부가 기록되어 있습니다.

이런 정보들을 조합하면 "어떤 특성을 가진 사람들이 생존했을까?"라는 질문에 답할 수 있습니다. 김개발 씨는 궁금해졌습니다.

"왜 하필 타이타닉 데이터일까요?" 팀장님이 웃으며 답했습니다. "좋은 질문이네요.

이 데이터는 세 가지 장점이 있어요." 첫째, 데이터 크기가 적당합니다. 약 900명의 승객 정보만 들어있어 노트북에서도 빠르게 처리할 수 있습니다.

너무 큰 데이터는 초보자에게 부담스럽지만, 타이타닉 데이터는 딱 좋습니다. 둘째, 결측치와 이상치가 포함되어 있습니다.

실제 데이터는 항상 완벽하지 않습니다. 나이 정보가 빠진 승객도 있고, 이상한 값이 들어있기도 합니다.

이런 문제를 처리하는 연습을 할 수 있습니다. 셋째, 명확한 분석 목표가 있습니다.

"누가 살아남았을까?"라는 질문은 데이터 분석의 완벽한 목표입니다. 이 질문에 답하기 위해 데이터를 탐색하고, 시각화하고, 패턴을 찾아내는 과정을 배울 수 있습니다.

코드를 살펴보겠습니다. 먼저 pandas, numpy, matplotlib, seaborn을 불러옵니다.

이것들은 데이터 분석의 4대 천왕이라고 불릴 만큼 중요한 라이브러리입니다. pandas는 데이터를 다루고, numpy는 수치 계산을, matplotlib과 seaborn은 시각화를 담당합니다.

한글 폰트 설정은 왜 필요할까요? 그래프에 한글을 넣으면 네모 박스로 깨져서 보이는 경우가 있습니다.

미리 폰트를 설정해두면 이런 문제를 예방할 수 있습니다. warnings.filterwarnings('ignore')는 경고 메시지를 숨겨줍니다.

분석 중에 나오는 수많은 경고 메시지는 초보자를 혼란스럽게 만들 수 있습니다. 물론 실무에서는 경고 메시지도 꼼꼼히 확인해야 하지만, 학습 단계에서는 숨겨두는 것이 좋습니다.

실무에서는 어떻게 활용될까요? 김개발 씨가 속한 회사는 이커머스 플랫폼을 운영합니다.

고객 데이터를 분석할 때도 타이타닉 데이터에서 배운 기법을 그대로 사용합니다. "어떤 고객이 재구매할까?", "어떤 특성을 가진 사람이 프리미엄 회원이 될까?" 같은 질문에 답하는 방식이 똑같습니다.

한 가지 주의할 점이 있습니다. 타이타닉 데이터는 연습용입니다.

실제 비즈니스 데이터는 훨씬 복잡하고 지저분합니다. 하지만 기본기를 탄탄히 다져두면 어떤 데이터가 와도 당황하지 않을 수 있습니다.

김개발 씨는 이제 준비가 끝났습니다. 라이브러리를 불러왔고, 설정도 마쳤습니다.

이제 본격적으로 데이터를 탐험할 시간입니다.

실전 팁

💡 - 데이터 분석을 시작할 때는 항상 필요한 라이브러리를 먼저 불러오세요

  • 한글 시각화를 할 계획이라면 미리 폰트 설정을 해두는 것이 좋습니다

2. 데이터 로드 및 기본 탐색

김개발 씨는 파일을 열어보려고 했습니다. 그런데 파일 확장자가 csv였습니다.

엑셀처럼 더블클릭으로 열 수는 없을까요? 팀장님이 다가와 말했습니다.

"pandas로 불러오면 됩니다."

데이터 로드는 데이터 분석의 첫 단계입니다. csv 파일을 pandas DataFrame으로 불러오면 데이터를 자유롭게 조작할 수 있습니다.

head(), info(), describe() 같은 메서드로 데이터의 전체 구조를 빠르게 파악할 수 있습니다.

다음 코드를 살펴봅시다.

# 타이타닉 데이터 불러오기
df = pd.read_csv('titanic.csv')

# 처음 5개 행 확인하기
print(df.head())

# 데이터 정보 확인 (컬럼, 타입, 결측치)
print(df.info())

# 기본 통계량 확인
print(df.describe())

# 데이터 크기 확인
print(f"전체 승객 수: {len(df)}명")

김개발 씨는 csv 파일을 처음 다뤄봤습니다. "csv가 뭐예요?" 팀장님이 설명해주셨습니다.

"Comma-Separated Values의 약자예요. 쉽게 말해서 쉼표로 구분된 텍스트 파일이죠." csv 파일은 마치 엑셀을 텍스트로 저장한 것과 같습니다.

각 데이터는 쉼표로 구분되고, 각 줄은 하나의 행을 나타냅니다. 단순하지만 강력한 형식입니다.

어떤 프로그램에서든 읽을 수 있고, 용량도 작습니다. 그렇다면 이 파일을 어떻게 불러올까요?

엑셀처럼 더블클릭으로는 안 됩니다. 코드로 불러와야 합니다.

바로 이때 pandas가 등장합니다. pd.read_csv('titanic.csv')라는 한 줄이면 충분합니다.

이 코드는 csv 파일을 읽어서 DataFrame이라는 특별한 형태로 변환해줍니다. DataFrame은 pandas의 핵심 데이터 구조입니다.

DataFrame을 무엇이라고 설명할 수 있을까요? 마치 엑셀 시트와 같습니다.

행과 열로 이루어져 있고, 각 열은 이름을 가지고 있습니다. 하지만 엑셀보다 훨씬 강력합니다.

수백만 개의 행도 빠르게 처리할 수 있고, 복잡한 연산도 한 줄로 수행할 수 있습니다. 데이터를 불러왔으니 이제 살펴봐야 합니다.

첫 번째로 사용하는 것이 head() 메서드입니다. df.head()를 실행하면 처음 5개 행이 출력됩니다.

전체 데이터를 보면 화면이 넘쳐나지만, 처음 몇 줄만 보면 데이터가 어떻게 생겼는지 감을 잡을 수 있습니다. 김개발 씨가 head()를 실행했더니 PassengerId, Survived, Pclass, Name, Sex, Age 같은 컬럼들이 보였습니다.

"아, 이런 정보들이 들어있구나." 두 번째로 info() 메서드를 사용합니다. info()는 데이터의 건강검진 같은 것입니다.

전체 행이 몇 개인지, 각 컬럼의 데이터 타입이 무엇인지, 결측치는 몇 개인지 알려줍니다. 예를 들어 Age 컬럼에 714개의 값만 있다면, 나머지는 결측치라는 뜻입니다.

팀장님이 강조했습니다. "info()는 꼭 확인하세요.

결측치를 모르고 분석하면 잘못된 결론을 내릴 수 있어요." 세 번째로 describe() 메서드입니다. describe()는 숫자 컬럼들의 통계를 보여줍니다.

평균, 표준편차, 최솟값, 최댓값, 사분위수 등이 한눈에 들어옵니다. Age 컬럼의 평균이 29.7세라면, 승객들의 평균 나이가 대략 30세라는 것을 알 수 있습니다.

마지막으로 len(df)로 전체 행 개수를 확인합니다. 타이타닉 데이터에는 약 891명의 승객 정보가 들어있습니다.

실제 승객은 2,224명이었지만, 데이터셋에는 일부만 포함되어 있습니다. 실무에서는 어떻게 활용할까요?

김개발 씨의 회사에서 고객 데이터를 분석할 때도 똑같은 순서를 따릅니다. 먼저 read_csv()로 데이터를 불러오고, head()로 대충 훑어보고, info()로 결측치를 확인하고, describe()로 통계를 봅니다.

이 네 단계만 거치면 데이터의 80%는 이해한 셈입니다. 한 가지 주의할 점이 있습니다.

csv 파일의 경로를 정확히 입력해야 합니다. 파일이 같은 폴더에 있다면 'titanic.csv'만 쓰면 되지만, 다른 폴더에 있다면 전체 경로를 써야 합니다.

경로를 잘못 쓰면 FileNotFoundError가 발생합니다. 김개발 씨는 이제 데이터가 어떻게 생겼는지 알았습니다.

891명의 승객, 12개의 컬럼, 일부 결측치. 이제 본격적으로 분석을 시작할 수 있습니다.

실전 팁

💡 - 데이터를 불러온 후 head(), info(), describe()는 항상 실행하세요

  • info()에서 결측치 비율이 높은 컬럼은 나중에 처리 방법을 고민해야 합니다

3. 생존율 기본 통계

김개발 씨는 가장 궁금한 것을 물어봤습니다. "전체 생존율은 얼마나 되나요?" 팀장님이 답했습니다.

"value_counts()를 사용해보세요."

생존율 계산은 타이타닉 분석의 핵심입니다. Survived 컬럼의 값을 집계하면 생존자와 사망자 수를 알 수 있습니다.

value_counts()와 mean()을 활용하면 빠르게 생존율을 계산할 수 있습니다.

다음 코드를 살펴봅시다.

# 생존 여부 집계 (0: 사망, 1: 생존)
survival_counts = df['Survived'].value_counts()
print("생존자 vs 사망자:")
print(survival_counts)

# 생존율 계산
survival_rate = df['Survived'].mean()
print(f"\n전체 생존율: {survival_rate:.2%}")

# 생존자와 사망자 수
survived = df['Survived'].sum()
total = len(df)
print(f"생존자: {survived}명 / 전체: {total}명")

김개발 씨는 Survived 컬럼을 유심히 봤습니다. 0과 1만 들어있었습니다.

"0이 사망이고 1이 생존이라는 뜻인가요?" 팀장님이 고개를 끄덕였습니다. "맞아요.

이런 방식을 이진 분류라고 해요." 이진 분류는 마치 스위치와 같습니다. 켜짐 아니면 꺼짐, 생존 아니면 사망.

두 가지 상태만 존재합니다. 이렇게 0과 1로 표현하면 계산하기도 편리합니다.

그렇다면 생존자가 몇 명인지 어떻게 알 수 있을까요? 가장 간단한 방법은 value_counts() 메서드입니다.

df['Survived'].value_counts()를 실행하면 0과 1이 각각 몇 개인지 세어줍니다. 예를 들어 0이 549개, 1이 342개라면 549명이 사망하고 342명이 생존한 것입니다.

김개발 씨가 실행해봤습니다. "549명이 죽고 342명이 살았네요.

생존율은 얼마나 될까요?" 계산기를 꺼낼 필요가 없습니다. mean() 메서드가 알아서 해줍니다.

df['Survived'].mean()을 실행하면 생존율이 나옵니다. 0과 1의 평균을 구하는 것인데, 왜 생존율이 나올까요?

마치 시험 점수의 평균을 구하는 것과 같습니다. 1(생존)이 많으면 평균이 높아지고, 0(사망)이 많으면 평균이 낮아집니다.

결과는 약 0.38입니다. 즉, 38%의 승객만 생존했습니다.

김개발 씨는 충격을 받았습니다. "10명 중 6명이 죽었다는 뜻이네요." 타이타닉 사고가 얼마나 참혹했는지 숫자로 느낄 수 있었습니다.

이것이 데이터의 힘입니다. 추상적인 사건이 구체적인 숫자로 다가옵니다.

sum() 메서드도 유용합니다. df['Survived'].sum()을 실행하면 생존자 수가 나옵니다.

1을 모두 더하면 생존자 수가 되는 간단한 원리입니다. len(df)와 함께 사용하면 "342명 중 891명"처럼 표현할 수 있습니다.

실무에서는 어떻게 활용할까요? 김개발 씨의 회사에서 이메일 마케팅 캠페인을 진행했다고 가정해봅시다.

고객이 이메일을 열었는지 안 열었는지를 0과 1로 기록합니다. value_counts()로 오픈율을 계산하고, mean()으로 전체 오픈율을 구합니다.

타이타닉 생존율을 구하는 것과 똑같은 방식입니다. 한 가지 주의할 점이 있습니다.

Survived 컬럼에 결측치가 있으면 계산이 달라집니다. 다행히 타이타닉 데이터의 Survived 컬럼에는 결측치가 없습니다.

하지만 실무 데이터에서는 항상 결측치를 확인해야 합니다. 팀장님이 말했습니다.

"38%라는 숫자만 봐서는 부족해요. 누가 살았고 누가 죽었는지 더 자세히 봐야 합니다." 김개발 씨는 고개를 끄덕였습니다.

전체 생존율은 알았지만, 이제 더 깊이 파고들어야 할 시간입니다.

실전 팁

💡 - 이진 분류 데이터(0과 1)는 mean()으로 비율을 쉽게 구할 수 있습니다

  • value_counts()에 normalize=True를 추가하면 비율로 바로 출력됩니다

4. 성별에 따른 생존율

김개발 씨는 영화 타이타닉을 떠올렸습니다. "여자와 어린이 먼저"라는 대사가 생각났습니다.

"실제로도 여성의 생존율이 높았을까요?" 팀장님이 미소를 지었습니다. "직접 확인해보세요."

그룹별 분석은 데이터 분석의 핵심 기법입니다. groupby()를 사용하면 성별, 나이, 등급 등으로 그룹을 나누어 각각의 생존율을 계산할 수 있습니다.

성별에 따른 생존율을 비교하면 흥미로운 패턴을 발견할 수 있습니다.

다음 코드를 살펴봅시다.

# 성별에 따른 생존율
gender_survival = df.groupby('Sex')['Survived'].mean()
print("성별 생존율:")
print(gender_survival)

# 성별 인원수와 생존자 수
gender_stats = df.groupby('Sex')['Survived'].agg(['count', 'sum', 'mean'])
gender_stats.columns = ['전체', '생존자', '생존율']
print("\n성별 상세 통계:")
print(gender_stats)

# 생존율을 퍼센트로 표시
gender_stats['생존율'] = gender_stats['생존율'] * 100

김개발 씨는 Sex 컬럼을 봤습니다. 'male'과 'female' 두 가지 값만 있었습니다.

"성별로 나눠서 생존율을 보면 재밌겠는데요." 팀장님이 말했습니다. "바로 그거예요.

**groupby()**를 사용하면 됩니다." **groupby()**는 마치 물건을 분류하는 것과 같습니다. 빨간 공과 파란 공이 섞여 있다고 상상해보세요.

groupby()는 빨간 공끼리, 파란 공끼리 자동으로 분류해줍니다. 데이터도 마찬가지입니다.

남성 데이터끼리, 여성 데이터끼리 모아줍니다. 그렇다면 어떻게 사용할까요?

df.groupby('Sex')['Survived'].mean()이라는 코드를 뜯어봅시다. 먼저 groupby('Sex')로 성별로 그룹을 나눕니다.

그 다음 ['Survived']로 생존 여부 컬럼만 선택합니다. 마지막으로 mean()으로 각 그룹의 평균을 구합니다.

결과가 나왔습니다. 여성의 생존율은 약 74%, 남성의 생존율은 약 19%였습니다.

김개발 씨는 깜짝 놀랐습니다. "여성이 남성보다 3배 이상 높네요!" 영화에서 본 장면이 실제였던 것입니다.

"여자와 어린이 먼저"라는 원칙이 실제로 지켜졌습니다. 구명보트에 여성과 어린이를 먼저 태웠기 때문입니다.

하지만 생존율만으로는 부족합니다. 전체 인원과 생존자 수도 함께 봐야 합니다.

agg() 메서드를 사용하면 여러 통계를 한 번에 계산할 수 있습니다. agg(['count', 'sum', 'mean'])은 개수, 합계, 평균을 모두 구해줍니다.

count는 전체 인원, sum은 생존자 수, mean은 생존율입니다. 결과를 보니 전체 남성은 577명인데 생존자는 109명, 전체 여성은 314명인데 생존자는 233명이었습니다.

김개발 씨가 계산해봤습니다. "남성 승객이 더 많았는데 생존자는 여성이 더 많네요." 이것이 바로 생존율의 차이입니다.

절대적인 숫자도 중요하지만, 비율을 봐야 진실이 보입니다. 실무에서는 어떻게 활용될까요?

김개발 씨의 회사에서 앱 사용자를 분석한다고 가정해봅시다. 연령대별, 성별별, 지역별로 나눠서 구매 전환율을 계산합니다.

groupby('age_group')['purchased'].mean()처럼 똑같이 사용합니다. 어떤 그룹이 구매를 많이 하는지 파악할 수 있습니다.

팀장님이 조언했습니다. "groupby()는 데이터 분석의 핵심이에요.

익숙해지면 어떤 데이터든 자유자재로 다룰 수 있어요." 한 가지 주의할 점이 있습니다. groupby()를 사용할 때는 결측치를 조심해야 합니다.

Sex 컬럼에 결측치가 있다면 해당 행은 그룹에 포함되지 않습니다. 다행히 타이타닉 데이터의 Sex 컬럼에는 결측치가 없습니다.

김개발 씨는 이제 확신했습니다. 데이터는 이야기를 담고 있습니다.

숫자 뒤에는 실제 사람들의 운명이 있습니다. 여성 승객들의 74%가 살아남은 것은 단순한 숫자가 아니라 실제로 일어난 일입니다.

실전 팁

💡 - groupby()와 agg()를 조합하면 여러 통계를 한 번에 계산할 수 있습니다

  • 생존율을 퍼센트로 표시하면 더 직관적입니다 (값에 100을 곱하기)

5. 객실 등급별 생존율

김개발 씨는 Pclass 컬럼을 발견했습니다. 1, 2, 3이라는 숫자가 보였습니다.

"이게 객실 등급인가요?" 팀장님이 답했습니다. "맞아요.

1등석, 2등석, 3등석이죠."

객실 등급은 타이타닉 승객의 사회적 지위를 나타냅니다. 1등석은 부유층, 3등석은 서민층이었습니다.

객실 등급에 따라 생존율이 어떻게 달라지는지 분석하면 당시의 계급 차이를 확인할 수 있습니다.

다음 코드를 살펴봅시다.

# 객실 등급별 생존율
class_survival = df.groupby('Pclass')['Survived'].mean()
print("객실 등급별 생존율:")
print(class_survival)

# 객실 등급별 상세 통계
class_stats = df.groupby('Pclass')['Survived'].agg(['count', 'sum', 'mean'])
class_stats.columns = ['전체 인원', '생존자', '생존율']
print("\n객실 등급별 상세 통계:")
print(class_stats)

# 객실 등급과 성별을 함께 고려
class_gender_survival = df.groupby(['Pclass', 'Sex'])['Survived'].mean().unstack()
print("\n등급과 성별을 함께 고려한 생존율:")
print(class_gender_survival)

김개발 씨는 Pclass 컬럼이 궁금했습니다. "1, 2, 3이면 1이 제일 좋은 거죠?" 팀장님이 설명했습니다.

"맞아요. 1등석은 최고급 객실이고, 3등석은 가장 저렴한 객실이에요." 객실 등급은 마치 비행기의 일등석, 이코노미석과 같습니다.

같은 배에 타고 있지만 대우가 완전히 다릅니다. 1등석 승객은 배의 위쪽에 있었고, 3등석 승객은 아래쪽에 있었습니다.

그렇다면 이런 차이가 생존에 영향을 미쳤을까요? groupby('Pclass')['Survived'].mean()을 실행해봅시다.

결과를 보니 1등석 생존율은 약 63%, 2등석은 약 47%, 3등석은 약 24%였습니다. 김개발 씨는 할 말을 잃었습니다.

"1등석이 3등석보다 2배 이상 높네요." 이것이 현실이었습니다. 배가 침몰할 때 구명보트는 위쪽 갑판에 있었습니다.

1등석 승객들은 갑판에 빠르게 도착할 수 있었지만, 3등석 승객들은 미로 같은 복도를 헤매야 했습니다. 일부는 문이 잠겨서 아예 나갈 수 없었습니다.

숫자를 더 자세히 봅시다. 1등석은 216명 중 136명이 생존했습니다.

2등석은 184명 중 87명, 3등석은 491명 중 119명만 살았습니다. 3등석 승객이 가장 많았는데 생존자는 가장 적었습니다.

김개발 씨는 불공평하다고 느꼈습니다. "같은 돈을 내고 탔는데 생존율이 이렇게 다르다니요." 팀장님이 말했습니다.

"데이터는 냉정합니다. 우리가 보고 싶지 않은 진실도 보여주죠." 더 흥미로운 분석을 해봅시다.

객실 등급과 성별을 함께 고려하면 어떨까요? groupby(['Pclass', 'Sex'])['Survived'].mean().unstack()을 실행합니다.

여기서 unstack()은 결과를 표 형태로 만들어줍니다. 행은 객실 등급, 열은 성별입니다.

결과를 보니 1등석 여성의 생존율은 97%에 달했습니다. 거의 모든 1등석 여성이 살아남았습니다.

반면 3등석 남성의 생존율은 14%에 불과했습니다. 김개발 씨는 패턴을 발견했습니다.

"성별도 중요하고, 객실 등급도 중요하네요. 둘 다 높으면 생존율이 급격히 올라가고요." 바로 그것입니다.

여러 요인을 함께 고려하면 더 정확한 그림이 그려집니다. 단순히 성별만 보면 부족하고, 객실 등급만 보면 부족합니다.

둘을 함께 봐야 전체 이야기가 보입니다. 실무에서는 어떻게 활용될까요?

김개발 씨의 회사에서 구독 서비스를 제공한다고 가정해봅시다. 무료 사용자, 베이직 사용자, 프리미엄 사용자를 등급별로 나눕니다.

각 등급별로 재구매율을 계산하고, 연령대와 함께 고려하면 "어떤 등급의 어떤 연령대가 충성도가 높은가"를 알 수 있습니다. 한 가지 주의할 점이 있습니다.

여러 개의 컬럼으로 groupby()를 할 때는 대괄호 안에 리스트로 넣어야 합니다. groupby(['Pclass', 'Sex'])처럼 말이죠.

하나만 넣을 때는 groupby('Pclass')처럼 그냥 써도 됩니다. 팀장님이 말했습니다.

"데이터는 역사를 기록합니다. 100년 전 그날 밤에 일어난 일을 숫자로 보여주고 있어요." 김개발 씨는 데이터 분석의 의미를 깨달았습니다.

단순히 숫자를 계산하는 것이 아니라 역사를 읽어내는 것입니다.

실전 팁

💡 - 여러 컬럼으로 groupby()를 하면 더 세밀한 분석이 가능합니다

  • unstack()을 사용하면 다중 인덱스를 피벗 테이블처럼 보기 쉽게 만들 수 있습니다

6. 나이와 생존율 관계

김개발 씨는 Age 컬럼을 봤습니다. 숫자가 너무 다양했습니다.

"나이도 생존에 영향을 미쳤을까요?" 팀장님이 답했습니다. "나이대로 그룹을 나눠보세요."

나이는 연속형 변수이므로 그대로 분석하기 어렵습니다. cut() 함수로 나이대로 구간을 나누면 분석이 쉬워집니다.

어린이, 청소년, 성인, 노인으로 나눠서 각 그룹의 생존율을 비교할 수 있습니다.

다음 코드를 살펴봅시다.

# 나이 결측치 확인
print(f"나이 결측치: {df['Age'].isnull().sum()}개")

# 나이대별로 구간 나누기
df['AgeGroup'] = pd.cut(df['Age'], bins=[0, 12, 18, 35, 60, 100],
                         labels=['어린이', '청소년', '청년', '중년', '노년'])

# 나이대별 생존율
age_survival = df.groupby('AgeGroup')['Survived'].mean()
print("\n나이대별 생존율:")
print(age_survival)

# 나이대별 상세 통계
age_stats = df.groupby('AgeGroup')['Survived'].agg(['count', 'sum', 'mean'])
print("\n나이대별 상세 통계:")
print(age_stats)

김개발 씨는 Age 컬럼을 살펴봤습니다. 0.42, 22, 35, 58 같은 숫자들이 보였습니다.

"나이가 너무 다양한데 어떻게 분석하죠?" 팀장님이 설명했습니다. "연속형 변수는 그대로 분석하기 어려워요.

구간으로 나눠야 합니다." 연속형 변수는 마치 온도계와 같습니다. 20도, 20.5도, 21도처럼 무한히 많은 값을 가질 수 있습니다.

이런 데이터를 그대로 groupby()하면 그룹이 너무 많아져서 분석이 어렵습니다. 해결 방법은 구간화입니다.

온도를 춥다, 보통, 덥다로 나누는 것처럼 나이도 어린이, 청소년, 성인으로 나눕니다. pandas의 cut() 함수가 이 일을 해줍니다.

pd.cut(df['Age'], bins=[0, 12, 18, 35, 60, 100])을 살펴봅시다. bins는 구간의 경계를 나타냅니다.

0-12는 어린이, 12-18은 청소년, 18-35는 청년, 35-60은 중년, 60-100은 노년입니다. labels 파라미터로 각 구간에 이름을 붙일 수 있습니다.

김개발 씨가 실행했습니다. "새로운 컬럼이 생겼네요!" df['AgeGroup']이라는 새 컬럼이 만들어졌습니다.

각 승객의 나이가 어느 구간에 속하는지 표시되어 있습니다. 이제 나이대별 생존율을 구할 수 있습니다.

groupby('AgeGroup')['Survived'].mean()을 실행하니 흥미로운 결과가 나왔습니다. 어린이의 생존율은 약 54%, 청소년은 약 40%, 청년은 약 35%였습니다.

김개발 씨가 말했습니다. "어린이가 제일 높네요.

'여자와 어린이 먼저'가 실제로 지켜진 거네요." 맞습니다. 구명보트에 어린이를 우선적으로 태웠기 때문입니다.

하지만 성인보다 높다고 해도 54%는 여전히 낮은 수치입니다. 어린이 10명 중 5명만 살아남았다는 뜻입니다.

그런데 문제가 하나 있습니다. Age 컬럼에는 결측치가 많습니다.

df['Age'].isnull().sum()을 실행하면 약 177개의 결측치가 있음을 알 수 있습니다. 전체 891명 중 177명의 나이를 모른다는 뜻입니다.

팀장님이 설명했습니다. "결측치는 분석에서 제외됩니다.

그래서 나이대별 통계의 전체 인원을 다 더해도 891이 안 돼요." 결측치를 어떻게 처리할까요? 세 가지 방법이 있습니다.

첫째, 그냥 무시하기. 나이를 모르는 승객은 분석에서 빼버립니다.

둘째, 평균값으로 채우기. Age의 평균인 약 30세로 결측치를 채웁니다.

셋째, 다른 정보로 추정하기. 이름의 호칭(Mr, Miss 등)으로 대략적인 나이를 추정합니다.

지금은 첫 번째 방법을 사용했습니다. 간단하지만 정보를 잃어버리는 단점이 있습니다.

실무에서는 어떻게 활용될까요? 김개발 씨의 회사에서 사용자 데이터를 분석할 때도 나이를 구간화합니다.

10대, 20대, 30대로 나눠서 각 연령대의 구매 패턴을 분석합니다. cut() 함수는 이런 작업을 손쉽게 만들어줍니다.

한 가지 주의할 점이 있습니다. 구간을 어떻게 나누느냐에 따라 결과가 달라질 수 있습니다.

어린이를 0-12로 할지 0-15로 할지, 이런 선택이 분석에 영향을 줍니다. 명확한 기준이 있다면 좋지만, 없다면 여러 방식으로 시도해봐야 합니다.

김개발 씨는 배웠습니다. 연속형 데이터는 구간화해야 분석하기 쉽다는 것을.

그리고 결측치는 항상 조심해야 한다는 것을.

실전 팁

💡 - cut() 함수는 연속형 변수를 범주형으로 변환할 때 매우 유용합니다

  • 결측치 비율이 높으면 분석 결과의 신뢰도가 떨어질 수 있습니다

7. 상관관계 히트맵 그리기

팀장님이 말했습니다. "이제 마지막 단계예요.

모든 변수 간의 관계를 한눈에 보는 거죠." 김개발 씨가 물었습니다. "어떻게요?" "히트맵을 그려봅시다."

상관관계 히트맵은 여러 변수 간의 관계를 색상으로 표현한 그래프입니다. 양의 상관관계는 밝은 색, 음의 상관관계는 어두운 색으로 표시됩니다.

seaborn의 heatmap()을 사용하면 아름다운 히트맵을 쉽게 그릴 수 있습니다.

다음 코드를 살펴봅시다.

# 숫자 컬럼만 선택
numeric_cols = df[['Survived', 'Pclass', 'Age', 'SibSp', 'Parch', 'Fare']]

# 상관관계 계산
correlation = numeric_cols.corr()
print("상관관계 매트릭스:")
print(correlation)

# 히트맵 그리기
plt.figure(figsize=(10, 8))
sns.heatmap(correlation, annot=True, cmap='coolwarm', center=0,
            fmt='.2f', linewidths=1, square=True)
plt.title('타이타닉 변수 간 상관관계')
plt.tight_layout()
plt.savefig('titanic_correlation_heatmap.png')
plt.show()

김개발 씨는 지금까지 변수를 하나씩 봤습니다. 성별, 객실 등급, 나이.

그런데 이것들을 한 번에 볼 수는 없을까요? 팀장님이 말했습니다.

"히트맵을 그려보세요. 모든 관계가 한눈에 들어옵니다." 히트맵은 마치 체온계처럼 숫자를 색으로 표현합니다.

높은 온도는 빨간색, 낮은 온도는 파란색. 상관관계도 마찬가지입니다.

강한 양의 상관관계는 빨간색, 강한 음의 상관관계는 파란색으로 표시됩니다. 그렇다면 상관관계란 무엇일까요?

두 변수가 함께 움직이는 정도를 나타냅니다. A가 증가하면 B도 증가한다면 양의 상관관계입니다.

A가 증가하면 B는 감소한다면 음의 상관관계입니다. 서로 무관하다면 상관관계가 0에 가깝습니다.

먼저 숫자 컬럼만 선택해야 합니다. 상관관계는 숫자끼리만 계산할 수 있습니다.

Name이나 Sex 같은 문자 컬럼은 사용할 수 없습니다. Survived, Pclass, Age, SibSp, Parch, Fare 같은 숫자 컬럼만 골라냅니다.

SibSp와 Parch가 뭘까요? SibSp는 함께 탄 형제자매 및 배우자 수, Parch는 함께 탄 부모 및 자녀 수입니다.

Fare는 요금입니다. 이제 corr() 메서드로 상관관계를 계산합니다.

numeric_cols.corr()을 실행하면 상관관계 매트릭스가 나옵니다. 행과 열에 모든 변수가 나열되고, 각 칸에는 두 변수 간의 상관계수가 표시됩니다.

상관계수는 -1에서 1 사이의 값입니다. 김개발 씨가 결과를 봤습니다.

Survived와 Pclass의 상관계수는 약 -0.34였습니다. "음수네요?" 팀장님이 설명했습니다.

"Pclass가 높을수록(1등석에서 3등석으로) 생존율이 낮아진다는 뜻이에요. 음의 상관관계죠." 반대로 Survived와 Fare의 상관계수는 약 0.26으로 양수입니다.

요금을 많이 낼수록 생존율이 높아진다는 뜻입니다. 당연합니다.

비싼 요금을 내면 좋은 객실에 머물고, 좋은 객실은 갑판에 가까우니까요. 이제 이것을 시각화합니다.

**sns.heatmap()**이 주인공입니다. 상관관계 매트릭스를 색상으로 표현해줍니다.

annot=True는 각 칸에 숫자를 표시하고, cmap='coolwarm'은 색상 팔레트를 지정합니다. 빨간색은 양의 상관관계, 파란색은 음의 상관관계입니다.

fmt='.2f'는 소수점 둘째 자리까지만 표시합니다. linewidths=1은 칸 사이에 선을 그어줍니다.

square=True는 각 칸을 정사각형으로 만듭니다. 김개발 씨가 히트맵을 봤습니다.

"와, 한눈에 들어오네요!" Survived 행을 보면 어떤 변수가 생존과 관련이 있는지 즉시 알 수 있습니다. Pclass는 음의 상관관계(파란색), Fare는 양의 상관관계(빨간색).

Age는 약한 음의 상관관계입니다. 대각선은 모두 1입니다.

당연합니다. 자기 자신과의 상관관계는 완벽하니까요.

실무에서는 어떻게 활용될까요? 김개발 씨의 회사에서 사용자 행동 데이터를 분석할 때도 히트맵을 그립니다.

앱 사용 시간, 방문 횟수, 구매 금액, 만족도 등의 상관관계를 한눈에 봅니다. "어떤 지표를 올리면 매출이 증가할까?"라는 질문에 답할 수 있습니다.

한 가지 주의할 점이 있습니다. 상관관계는 인과관계가 아닙니다.

A와 B가 상관관계가 있다고 해서 A가 B를 일으킨다는 뜻은 아닙니다. 예를 들어 Fare와 Survived가 상관관계가 있다고 해서 "돈을 많이 내면 살 수 있다"는 뜻은 아닙니다.

돈을 많이 내면 좋은 객실에 있고, 좋은 객실이 갑판에 가까워서 생존율이 높은 것입니다. 팀장님이 말했습니다.

"상관관계는 단서를 줍니다. 어디를 더 깊이 파야 할지 알려주죠." 김개발 씨는 이제 타이타닉 데이터를 완전히 이해했습니다.

각 변수를 하나씩 봤고, 변수 간의 관계도 봤습니다. 히트맵 하나로 전체 그림이 그려졌습니다.

plt.savefig()로 그래프를 파일로 저장할 수 있습니다. 보고서에 넣거나 다른 사람과 공유할 때 유용합니다.

김개발 씨는 팀장님께 감사의 인사를 전했습니다. "타이타닉 데이터 하나로 데이터 분석의 전체 과정을 배웠어요." 팀장님이 웃으며 답했습니다.

"이제 시작일 뿐이에요. 실전 데이터는 훨씬 복잡하지만, 기본은 똑같습니다.

데이터를 불러오고, 탐색하고, 시각화하고, 인사이트를 찾아내는 거죠."

실전 팁

💡 - 히트맵은 많은 변수 간의 관계를 빠르게 파악할 때 매우 유용합니다

  • 상관관계가 높다고 해서 인과관계가 있는 것은 아니므로 해석에 주의하세요

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Python#Pandas#Matplotlib#Seaborn#EDA

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.