codestates / codestates/ds-blog

[방승진] 200904 타이타닉 데이터 분석

Open
#55 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
No language data
Stars
2
Forks
4
PR merge metrics
No merged PRs in 30d

Description

타이타닉 데이터 분석

목차

1. 개요
2. 궁금한 점
3. 데이터 분석
1. 기본적인 데이터 구성
2. 좌석 등급별 생존율
3. 좌석 등급별 어린이 생존율 비교
4. 장소별 생존율 비교
4. 결론

---

1. 개요

97년 개봉했던 영화 '타이타닉'이 생각난다.

당시엔 이 영화가 제임스 카메론 감독이 만든 영화라던가,

레오가 이렇게 성공할 것이라던가,

알 만한 나이가 아니었던 걸로 기억한다.

물론 케이트 윈슬렛을 빼놓을 순 없지...

솔직히 이 글을 쓰기 위한 검색에서 놀랐다.

여배우가 케이트 윈슬렛이었어???

새삼 알게 되었다. 이 영화가 '대작'이었음을...

아직도 이 장면은 생생하다.

![타이타닉 사진1](https://user-images.githubusercontent.com/67680168/92208282-d489f380-eec5-11ea-9aa0-ca4956f73d1c.jpeg)

너무 어렸던 때지만,

또래 친구들이 이 장면을 따라하는 모습도 종종 봤던 것 같다.

서양도 크게 다르진 않은 듯...

![타이타닉 사진2(패러디)](https://user-images.githubusercontent.com/67680168/92208501-4cf0b480-eec6-11ea-91e7-e0e59c4dc127.jpg)
(갈매기에게 새우깡 대신 콧물을 주는 게 좀 다른 것 같기도?)

---

나름 재밌게 시작하려고 했지만...

사실, 대규모 인원이 희생된 안타까운 사건이었다.

총 2,224명의 인원 중 생존자는 단 706명, 생존율로 따지면 고작 31.74%라니까.

이번 글에선

Kaggle 에서 받은 891명의 일부 데이터를 토대로,

이 사건을 알게 되고 떠오른 궁금한 점 몇 가지를 토대로 기초적인 Python 수준에서 정리해보려고 한다.

이 글을 토대로 기초적인 Python 활용사례를 누군가 경험해보는 기회가 되었으면 좋겠다.

2. 궁금한 점



궁금증 1 : 여성과 아이를 먼저 구조하는 상황이 실제 벌어졌을까?

궁금증 2 : 부(wealth)에 따라 생존율에 차이가 있지 않을까?

궁금증 3 : 출발지 및 경유지가 총 3곳이던데, 장소별 생존율 차이가 있지 않을까?

크게 3 가지 궁금증이 생겼고,

주어진 자료만으로 찾아보는 기회를 가졌다.

3. 데이터 분석

**1. 기본적인 데이터 구성**

먼저 데이터 분석을 위한 기초 라이브러리인 Pandas와 Numpy를 불러왔다.

이를 통해 데이터의 기본적인 요소를 알아보고 범주형 자료에 해당하는 열을 matplotlib으로 대략적으로 그려봤다.

- Input

```py
from google.colab import drive
drive.mount('/content/drive')

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

df = pd.read_csv('/content/drive/My Drive/datasets_train.csv')

def bar_chart(feature):
Survived = df[df["Survived"] == 1][feature].value_counts()
Dead = df[df["Survived"] == 0][feature].value_counts()
df_train = pd.DataFrame([Survived, Dead])
df_train.index = ['Survived', 'Dead']
df_train.plot(kind = 'bar')

bar_chart('Sex')
bar_chart('Pclass')
bar_chart('Embarked')
bar_chart('Parch')
bar_chart('SibSp')
```

- Output

![스크린샷 2020-09-06 오후 4 09 21](https://user-images.githubusercontent.com/67680168/92320286-57908280-f05b-11ea-8ea5-faec8cbdb0b3.png)

![스크린샷 2020-09-06 오후 4 09 41](https://user-images.githubusercontent.com/67680168/92320300-60815400-f05b-11ea-8391-86c4104e7a9c.png)

첫 번째 바 차트를 보면, 여성 생존자가 상대적으로 많은 것을 알 수 있다.

두 번째 바 차트를 보면, 1등석 승객의 생존자가 가장 많고, 3등석 승객의 사망자가 압도적으로 많은 것을 알 수 있다.

세 번째 바 차트를 보면, 사우샘스턴(S)에서 탑승한 승객의 생존 및 사망자가 많다.

네 번째와 마지막 차트는 각각 Parch(부모와 아이 동반 인원), SibSp(형제, 자매 및 배우자 동반 인원)을 나타내는데,

추가로 알아낼 만한 것이 한 눈에 보이지 않는 것 같다.

---

먼저 궁금증 1("여성과 아이를 먼저 구조하는 상황이 실제 벌어졌을까?")을 알아보고자 했다.
위에서 보았던 바 차트를 통해 여성 생존자가 많다는 것은 이미 확인했고, 생존율을 구체적으로 알아보고자 한다.

- Input

```py
cnt_female = df[(df['Survived'] == 1) & (df['Sex'] == 'female')].shape[0]
cnt_male = df[(df['Survived'] == 1) & (df['Sex'] == 'male')].shape[0]
Total_surv = cnt_female + cnt_male

print("여성 생존자 비율 : ", np.round(cnt_female / Total_surv * 100, decimals=2), '%')
print("남성 생존자 비율 : ", np.round(cnt_male / Total_surv * 100, decimals=2), '%')
```

- Output

```
여성 생존자 비율 : 68.13 %
남성 생존자 비율 : 31.87 %
```

![생존자 성비구성](https://user-images.githubusercontent.com/67680168/92211692-cd65e400-eecb-11ea-9349-17dab4a4959f.png)

여성이 상대적으로 생존율이 높은 것으로 나타난다.

어린이(13세 미만 가정) 생존율은 어땠을까?

추후 좌석등급별 어린이 생존율 비교를 통한 항목에서 알아볼 것이다.

---

**2. 좌석 등급별 생존율**

다음으론 궁금증2("부(wealth)에 따라 생존율에 차이가 있지 않을까?")를 알아보았다.

이를 위해 좌석 등급을 부의 척도로 가정했다.

(1등석이 가장 비싸다.)

- Input

```py
# Pclass와 Survived를 가져온 후, Pclass로 묶는다. 그러면 각 Pclass마다 0, 1(Survived 값)이 count가 된다.
# 이를 통해 각 Pclass에 몇 명이 있는지 확인 가능하다.
df[['Pclass', 'Survived']].groupby(['Pclass'], as_index = True).count()
```

```py
# sum()을 통해 생존자의 합계를 알 수 있다.
df[['Pclass', 'Survived']].groupby(['Pclass'], as_index = True).sum()
```

```py
# Pclass별 생존율 구하기
# group화된 객체에 mean()을 통해 평균값(각 등급별 생존율)을 구할 수 있다.
print(np.round(df[['Pclass', 'Survived']].groupby(['Pclass'], as_index =True).mean() * 100, decimals = 2), '%')
```

```py
# by = column_set , ascending = True(오름차순) / False(내림차순)
df[['Pclass', 'Survived']].groupby(
['Pclass'], as_index = True).mean().sort_values(by = 'Survived', ascending = False
).plot.bar()
```

- Output

![스크린샷 2020-09-06 오후 3 54 50](https://user-images.githubusercontent.com/67680168/92320032-4fcfde80-f059-11ea-9fae-56974db94ddd.png)

![스크린샷 2020-09-06 오후 3 55 26](https://user-images.githubusercontent.com/67680168/92320037-62e2ae80-f059-11ea-9077-ebbebc52d181.png)

![스크린샷 2020-09-06 오후 3 55 57](https://user-images.githubusercontent.com/67680168/92320050-74c45180-f059-11ea-9a06-0988f13ae045.png)

![스크린샷 2020-09-06 오후 3 56 45](https://user-images.githubusercontent.com/67680168/92320063-91f92000-f059-11ea-87b2-ba2177d0da24.png)

1, 2, 3등석 승객순으로 생존율이 높은 것으로 나타난다.
이를 토대로 볼 때 부가 생존율의 척도(부자일수록 생존률이 높다)가 된 것으로 추측할 수 있다.

---

**3. 좌석 등급별 어린이 생존율 비교**

- Input

```py
#좌석등급별 어린이 탑승인원
youth_1 = df[(df['Age'] < 13) & (df['Pclass'] == 1)].shape[0]
youth_2 = df[(df['Age'] < 13) & (df['Pclass'] == 2)].shape[0]
youth_3 = df[(df['Age'] < 13) & (df['Pclass'] == 3)].shape[0]

print('1등석 어린이 탑승인원 : ', youth_1)
print('2등석 어린이 탑승인원 : ', youth_2)
print('3등석 어린이 탑승인원 : ', youth_3)

#좌석등급별 어린이 생존율
surv_youth_1 = df[(df['Age'] < 13) & (df['Pclass'] == 1) & (df['Survived'] == 1)].shape[0]
surv_youth_2 = df[(df['Age'] < 13) & (df['Pclass'] == 2) & (df['Survived'] == 1)].shape[0]
surv_youth_3 = df[(df['Age'] < 13) & (df['Pclass'] == 3) & (df['Survived'] == 1)].shape[0]

print("1등석 어린이 생존율 : ", np.round(surv_youth_1 / youth_1 * 100, decimals=2), '%')
print("2등석 어린이 생존율 : ", np.round(surv_youth_2 / youth_2 * 100, decimals=2), '%')
print("3등석 어린이 생존율 : ", np.round(surv_youth_3 / youth_3 * 100, decimals=2), '%')

#좌석등급별 어린이 사망률
dead_youth_1 = df[(df['Age'] < 13) & (df['Pclass'] == 1) & (df['Survived'] == 0)].shape[0]
dead_youth_2 = df[(df['Age'] < 13) & (df['Pclass'] == 2) & (df['Survived'] == 0)].shape[0]
dead_youth_3 = df[(df['Age'] < 13) & (df['Pclass'] == 3) & (df['Survived'] == 0)].shape[0]

print("1등석 어린이 사망률 : ", np.round(dead_youth_1 / youth_1 * 100, decimals=2), "%")
print("2등석 어린이 사망률 : ", np.round(dead_youth_2 / youth_2 * 100, decimals=2), "%")
print("3등석 어린이 사망률 : ", np.round(dead_youth_3 / youth_3 * 100, decimals=2), "%")
```

- Output
```
1등석 어린이 탑승인원 : 4
2등석 어린이 탑승인원 : 17
3등석 어린이 탑승인원 : 48

1등석 어린이 생존율 : 75.0 %
2등석 어린이 생존율 : 100.0 %
3등석 어린이 생존율 : 41.67 %

1등석 어린이 사망률 : 25.0 %
2등석 어린이 사망률 : 0.0 %
3등석 어린이 사망률 : 58.33 %
```

단순히 비율로 보면 2등석 어린이 생존율이 가장 높고, 1등석 어린이 생존율이 그 다음이므로
이 경우엔 부가 생존율의 척도로 작용하지 않는 것처럼 보인다.

그러나,
각 등급별 어린이 탑승인원을 보면 3등석 어린이 탑승인원이 가시적으로 많으며,
1등석 및 2등석 어린이 탑승인원은 상대적으로 적은 것으로 확인된다.

3등석 어린이의 생존율이 41.67%로,
가장 많은 인원이 속한 범주에서 가장 낮은 생존율을 보여준다.

이를 토대로 보면,
부가 생존율의 척도로 작용되었을 가능성을 부정하기 어렵다.
---

**4. 장소별 생존율 비교**

마지막 궁금증인 "장소별 생존율 차이가 있지 않을까?"를 알아보았다.

출발지는 영국의 사우샘프턴(Southampton),

경유지는 프랑스의 셰르부르(Cherbourg)와

아일랜드의 퀸즈 타운(Queens town)로,

원래대로라면 뉴욕에 도착했어야 했다.

![타이타닉 사진4(각 도시 그림)](https://user-images.githubusercontent.com/67680168/92212752-6a754c80-eecd-11ea-93a4-63628334b963.png)

- Input

```py
import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as plt

S_loca = np.round(depa_S / Total_surv * 100, decimals=2)
C_loca = np.round(depa_C / Total_surv * 100, decimals=2)
Q_loca = np.round(depa_Q / Total_surv * 100, decimals=2)

#장소별 생존율 차트
objects = ('Southampton', 'Cherbourg', 'Queenstown')
y_pos = np.arange(len(objects))
performance = [S_loca, C_loca, Q_loca]

plt.bar(y_pos, performance, align='center', alpha=0.5)
plt.xticks(y_pos, objects)
plt.ylabel('Survival rate')
plt.title('Survival rate by location')

plt.show()
```

- Output

![123](https://user-images.githubusercontent.com/67680168/92229375-5721ab80-eee4-11ea-94f5-3fe30d143d22.png)

상대적으로 출발지인 사우샘프턴에서 탑승한 승객들의 생존율이 압도적으로 높았다.

사용한 데이터가 일부 자료에 불과하기 때문에,

그 원인까지 알아내긴 어려울 것 같다.

하지만 추측은 해볼 수 있다.

등급별로 좌석이 분리되어 있다고 하더라도

등급 내 좌석 선점은 비교적 자유롭지 않았을까? (ex. 선착순)

4. 결론

위의 자료를 정리해보면서,
여성이 상대적으로 높은 생존율을 보인 것을 확인했다.
이를 토대로 여성이 먼저 구조대상이 되었을 가능성이 높음을 알 수 있다.
어린이 역시 먼저 구조대상이 되었을지는 위의 자료로는 확인하기 어렵다.(보완이 필요하다.)

또한 좌석등급별 생존율을 토대로,
비교적 부유할수록 생존율이 높은 것을 알 수 있었다.

장소별 생존율은 사우샘프턴이 가장 높았는데,
해당 자료만으로 장소에 따른 생존율 차이가 나타났는지는 단정짓기 어려워보인다.

---

**개인적인 생각 추가**

이번 글에서는 데이터를 정리하는데 어려움을 많이 느꼈다.
무엇보다 1, 2, 3등석 승객별 생존율을 잘못 산출해내서 고치는데 많은 시간을 투입했다.

그 주요 원인은 Pandas를 잘 다루지 못했다는 것, 즉 실력 부족이다.
추가로 과제 제출 당시 시간이 부족해서 퇴고를 제대로 하지 못하고 제출했다는 문제도 있다.

글은 잘 쓸 수도, 못 쓸 수도 있다.
못 썼다면 못 쓴 원인을 찾아내고 수정해나가면 된다.

그런데,
이번 과제는 치명적인 오류가 많았기 때문에,
수정하면서 개인적으로 준 점수는 1점이다.
(심지어 아직도 부족한 점이 많아 보인다.)

아마 첫 과제라,
너그러이 2점으로 평가를 해주신 것 같다.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.