2. EDA Process¶
- 분석의 목적 및 변수 확인
- 분석의 목적을 명확히 하여 raw data를 어떻게 바라봐야 할지를 결정한다.
- 각 Column이 지니는 의미, 데이터타입 등을 확인한다.
- 데이터를 전체적으로 살펴보기
- 데이터 사이의 상관관계 살피기
- 결측치가 존재하는지 등을 확인하기 (데이터전처리 방법이 달라질 수 있음)
- 데이터의 크기 살펴보기
- 데이터의 개별 속성을 파악하기
- 데이터의 속성과 데이터 값이 가지는 의미를 명확히 인지하기
EDA Example - Titanic¶
- Dataset : Titanic: Machine Learning from Disaster
In [2]:
## 0. 라이브러리 준비
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
In [5]:
# 1. 데이터 호출 및 전처리
## 데이터 호출
titanic_df = pd.read_csv("D:/workspaces/WinterStudy2022/datasetTitanic/train.csv")
1. 분석의 목적 및 변수 확인¶
- 목적 : 생존한 사람들의 특징 확인하기
- 필요변수 : 생존여부, 탑승자의 특징을 확인할 수 있는 변수
In [8]:
## 상위 5개 데이터 확인
titanic_df.head()
# Cabin Column에서 결측치 존재
# 결측치는 상황에 따라서 다르게 처리해야 하므로 일단 보류
Out[8]:
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
In [9]:
## 각 Columh의 데이터 타입 확인
titanic_df.dtypes
Out[9]:
PassengerId int64 Survived int64 Pclass int64 Name object Sex object Age float64 SibSp int64 Parch int64 Ticket object Fare float64 Cabin object Embarked object dtype: object
2. 데이터 전체적으로 살펴보기¶
In [12]:
## 데이터 전체 정보를 얻는 함수: dataframe_name.describe()
titanic_df.describe()
# 수치형 데이터에 대한 요약만을 제공하므로
# object타입인 데이터는 제공되지 않아 원본데이터에 비해 열이 줄어들었음.
Out[12]:
PassengerId | Survived | Pclass | Age | SibSp | Parch | Fare | |
---|---|---|---|---|---|---|---|
count | 891.000000 | 891.000000 | 891.000000 | 714.000000 | 891.000000 | 891.000000 | 891.000000 |
mean | 446.000000 | 0.383838 | 2.308642 | 29.699118 | 0.523008 | 0.381594 | 32.204208 |
std | 257.353842 | 0.486592 | 0.836071 | 14.526497 | 1.102743 | 0.806057 | 49.693429 |
min | 1.000000 | 0.000000 | 1.000000 | 0.420000 | 0.000000 | 0.000000 | 0.000000 |
25% | 223.500000 | 0.000000 | 2.000000 | 20.125000 | 0.000000 | 0.000000 | 7.910400 |
50% | 446.000000 | 0.000000 | 3.000000 | 28.000000 | 0.000000 | 0.000000 | 14.454200 |
75% | 668.500000 | 1.000000 | 3.000000 | 38.000000 | 1.000000 | 0.000000 | 31.000000 |
max | 891.000000 | 1.000000 | 3.000000 | 80.000000 | 8.000000 | 6.000000 | 512.329200 |
In [16]:
## 상관계수 확인 : dataframe_name.corr()
titanic_df.corr()
# 단, 상관성과 인과성을 구분해야 한다.
# 상관성 : 값의 전반적인 경향만을 나타냄
# 인과성 : 어떠한 사건이 벌어질 때 다른 사건과의 연관성을 나타냄.
# 상관계수에서는 "상관성"만을 나타낼 뿐, "인과성"까지 파악하지는 못한다.
Out[16]:
PassengerId | Survived | Pclass | Age | SibSp | Parch | Fare | |
---|---|---|---|---|---|---|---|
PassengerId | 1.000000 | -0.005007 | -0.035144 | 0.036847 | -0.057527 | -0.001652 | 0.012658 |
Survived | -0.005007 | 1.000000 | -0.338481 | -0.077221 | -0.035322 | 0.081629 | 0.257307 |
Pclass | -0.035144 | -0.338481 | 1.000000 | -0.369226 | 0.083081 | 0.018443 | -0.549500 |
Age | 0.036847 | -0.077221 | -0.369226 | 1.000000 | -0.308247 | -0.189119 | 0.096067 |
SibSp | -0.057527 | -0.035322 | 0.083081 | -0.308247 | 1.000000 | 0.414838 | 0.159651 |
Parch | -0.001652 | 0.081629 | 0.018443 | -0.189119 | 0.414838 | 1.000000 | 0.216225 |
Fare | 0.012658 | 0.257307 | -0.549500 | 0.096067 | 0.159651 | 0.216225 | 1.000000 |
In [19]:
## 결측치 확인
titanic_df.isnull().sum()
# age, cabin, embarked에서 결측치 발견
Out[19]:
PassengerId 0 Survived 0 Pclass 0 Name 0 Sex 0 Age 177 SibSp 0 Parch 0 Ticket 0 Fare 0 Cabin 687 Embarked 2 dtype: int64
3. 데이터의 개별 속성 파악하기¶
1. Survived Column¶
In [22]:
# 생존자 및 사망자의 인원 수
# 생존자 인원 수 : 생존 = 1이므로, 1의 개수는 곧 생존자 인원 수와 같다.
titanic_df['Survived'].sum()
Out[22]:
342
In [25]:
# dataframe_name['Column'].value_counts() : 지정된 열 내에 존재하는 값의 개수 반환
titanic_df['Survived'].value_counts()
Out[25]:
0 549 1 342 Name: Survived, dtype: int64
In [28]:
# 생존자 및 사망자의 인원 수를 BarPlot으로 표현
# sns.countplot()을 사용
# titanic_df에서 Survived를 기준으로 barplot을 추출하라.
sns.countplot(x = 'Survived', data = titanic_df)
plt.show()
2. Pclass (좌석등급)¶
In [31]:
# Pclass에 따른 인원파악
# groupby를 사용하여 파악한다.
# Pclass의 인원수 파악
titanic_df[['Pclass', 'Survived']].groupby(['Pclass']).count()
Out[31]:
Survived | |
---|---|
Pclass | |
1 | 216 |
2 | 184 |
3 | 491 |
In [35]:
# 생존자 인원수 파악
titanic_df[['Pclass', 'Survived']].groupby(['Pclass']).sum()
Out[35]:
Survived | |
---|---|
Pclass | |
1 | 136 |
2 | 87 |
3 | 119 |
In [43]:
# 생존자 비율 파악 (전체 탑승자 중 생존자 비율)
# 해당 데이터 기준으로
# 평균 = sum() : 생존자 / count() : 전체인원
# 생존자 비율 = 생존자 / 전체인원
# 으로 동일하기 떄문에 평균으로 구한다.
pclass = titanic_df[['Pclass', 'Survived']].groupby(['Pclass']).mean()
pclass
Out[43]:
Survived | |
---|---|
Pclass | |
1 | 0.629630 |
2 | 0.472826 |
3 | 0.242363 |
In [44]:
# 히트맵을 활용
sns.heatmap(pclass)
plt.show()
3. Sex(성별)¶
In [50]:
# Survived, Sex를 기준으로 묶기
titanic_df.groupby(['Survived', 'Sex']).count()
Out[50]:
PassengerId | Pclass | Name | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | ||
---|---|---|---|---|---|---|---|---|---|---|---|
Survived | Sex | ||||||||||
0 | female | 81 | 81 | 81 | 64 | 81 | 81 | 81 | 81 | 6 | 81 |
male | 468 | 468 | 468 | 360 | 468 | 468 | 468 | 468 | 62 | 468 | |
1 | female | 233 | 233 | 233 | 197 | 233 | 233 | 233 | 233 | 91 | 231 |
male | 109 | 109 | 109 | 93 | 109 | 109 | 109 | 109 | 45 | 109 |
In [51]:
# Survived, Sex를 기준으로 묶어서 표현한 데이터프레임 중 Survived 열에 접근하기
titanic_df.groupby(['Survived', 'Sex'])['Survived'].count()
Out[51]:
Survived Sex 0 female 81 male 468 1 female 233 male 109 Name: Survived, dtype: int64
In [54]:
# sns.catplot
sns.catplot(x = 'Sex', col = 'Survived', kind = 'count', data = titanic_df)
plt.show()
## 남성이 여성보다 많이 죽었고
## 여성이 남성보다 많이 살았음을 알 수 있다.
4. Age(나이)¶
- 경고 : 결측치가 존재한다
In [56]:
titanic_df.describe()['Age']
Out[56]:
count 714.000000 mean 29.699118 std 14.526497 min 0.420000 25% 20.125000 50% 28.000000 75% 38.000000 max 80.000000 Name: Age, dtype: float64
In [63]:
## Survived 1, 0과 Age의 경향성 파악
## 커널 밀도그림을 이용한다.
# subplot = 여러 개의 plot을 한 번에 보여주는 기능
# subplot(가로 plot개수, 세로 plot개수, figsize = (가로 길이, 세로 길이))
# 참고 : figure - axis - plot의 순으로 그래프가 그려진다.
# 그래서 그래프를 그리기 앞서 figure와 axis 설정을 한 것이다.
fig, ax = plt.subplots(1, 1, figsize = (10, 5))
# [dataframe_name[dataframe_name.Column == value]['Column'] =
# [dataframe의 Column에 들어간 값이 value인 "행"을 추출하는데]
# ['추출된 행 중에서 Column만 추출']
sns.kdeplot(x = titanic_df[titanic_df.Survived == 1]['Age'], ax = ax)
sns.kdeplot(x = titanic_df[titanic_df.Survived == 0]['Age'], ax = ax)
plt.legend(['Survived', 'Dead'])
plt.show()
# insight
# 1. 0세 ~ 10세 아이들은 비교적 많이 생존하였다.
# 2. 18세 ~ 30세 근처 연령의 사람들은 많이 사망하였다.
5. 성별 + Pclass와 Survived (복합적 요소일 경우의 EDA분석)¶
In [66]:
# 각 data별로 그려진 막대기 = 신뢰구간
sns.catplot(x = 'Pclass', y = 'Survived', hue = 'Sex', kind = 'point', data = titanic_df)
plt.show()
# Pclass = 1 or 2 and Sex = female일 경우, 생존할 가능성이 높음
6. 나이 + Pclass와 Survived¶
In [70]:
# titanic_df['Age'][titanic_df.Pclass == {value}].plot(kind = 'kde')
# titanic_df의 Age 열을 추출하는데
# titanic-df의 Pclass가 {value}일 경우만으로 제한하라.
# .plot(kind = 'kde') : 추출된 값을 kde plot으로 그려라
titanic_df['Age'][titanic_df.Pclass == 1].plot(kind = 'kde')
titanic_df['Age'][titanic_df.Pclass == 2].plot(kind = 'kde')
titanic_df['Age'][titanic_df.Pclass == 3].plot(kind = 'kde')
plt.legend(['1st class', '2nd class', '3rd class'])
plt.show()
Mission : 직접 해보기¶
1. 본문에서 언급된 Feature를 제외하고 유의마한 Feature를 1개 이상 찾기¶
2. Kaggle에서 Dataset을 찾고, 이 Dataset에서 유의미한 Feature를 3개 이상 찾고 이를 시각화하기¶
데이터 둘러보기
- 각 데이터는 어떤 자료형을 갖고 있는가?
- 데이터의 결측치는 없는가? 어떻게 다루어야 할까?
- 데이터의 자료형을 바꾸어주어야 하는가?
데이터에 대한 가설 세우기
- 개인의 경험 혹은 구체적 자료를 근거로 가설 설정
- 가설은 명확할수록 좋다.
가설을 검증하기 위한 증거 찾기
- 여러 데이터 가공 및 시각화 기술을 사용하여 증거 찾기
.groupby()
를 통하여 그룹화.merge()
를 통해 두 개 이상의 dataframe 병합- 시각화를 통해 잘 보여주기
- 2번 Mission은 다음날 EDA Project라는 이름으로 같은 Mission이 존재하므로 진행하지 않는다.
In [72]:
titanic_df.head()
Out[72]:
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
가설설정 : 형제자매가 많은 사람의 사망률이 더욱 높을 것이다.
- 부모가 자신의 아이를 더욱 많이 챙겨야 할수록 생존률이 떨어질 것이라고 예측했기 때문
In [73]:
titanic_df.describe()
Out[73]:
PassengerId | Survived | Pclass | Age | SibSp | Parch | Fare | |
---|---|---|---|---|---|---|---|
count | 891.000000 | 891.000000 | 891.000000 | 714.000000 | 891.000000 | 891.000000 | 891.000000 |
mean | 446.000000 | 0.383838 | 2.308642 | 29.699118 | 0.523008 | 0.381594 | 32.204208 |
std | 257.353842 | 0.486592 | 0.836071 | 14.526497 | 1.102743 | 0.806057 | 49.693429 |
min | 1.000000 | 0.000000 | 1.000000 | 0.420000 | 0.000000 | 0.000000 | 0.000000 |
25% | 223.500000 | 0.000000 | 2.000000 | 20.125000 | 0.000000 | 0.000000 | 7.910400 |
50% | 446.000000 | 0.000000 | 3.000000 | 28.000000 | 0.000000 | 0.000000 | 14.454200 |
75% | 668.500000 | 1.000000 | 3.000000 | 38.000000 | 1.000000 | 0.000000 | 31.000000 |
max | 891.000000 | 1.000000 | 3.000000 | 80.000000 | 8.000000 | 6.000000 | 512.329200 |
In [108]:
# 형제자매 인원수 별 생존자 및 사망자 파악
sib_dead_or_live = titanic_df.groupby(['Survived', 'SibSp'])['SibSp'].count()
print(sib_dead_or_live)
sib_dead_or_live[[0]]
Survived SibSp 0 0 398 1 97 2 15 3 12 4 15 5 5 8 7 1 0 210 1 112 2 13 3 4 4 3 Name: SibSp, dtype: int64
Out[108]:
Survived SibSp 0 0 398 1 97 2 15 3 12 4 15 5 5 8 7 Name: SibSp, dtype: int64
In [103]:
# 전체 형제자매 인원수 파악
sib_all = titanic_df[['Survived', 'SibSp']].groupby(['SibSp']).count()
sib_all
Out[103]:
Survived | |
---|---|
SibSp | |
0 | 608 |
1 | 209 |
2 | 28 |
3 | 16 |
4 | 18 |
5 | 5 |
8 | 7 |
In [106]:
print(sib_dead_or_live[[0]])
print(sib_dead_or_live[[1]])
Survived SibSp 0 0 398 1 97 2 15 3 12 4 15 5 5 8 7 Name: SibSp, dtype: int64 Survived SibSp 1 0 210 1 112 2 13 3 4 4 3 Name: SibSp, dtype: int64
In [123]:
sib_dead_or_live[[0][0]]
Out[123]:
SibSp 0 398 1 97 2 15 3 12 4 15 5 5 8 7 Name: Survived, dtype: int64
In [125]:
# Dataframe to Series
series_sib = sib_all.squeeze()
series_sib
Out[125]:
SibSp 0 608 1 209 2 28 3 16 4 18 5 5 8 7 Name: Survived, dtype: int64
In [131]:
# 각 부분에 해당하는 백분율 산출
percent_of_live = sib_dead_or_live / series_sib
percent_of_live
Out[131]:
Survived SibSp 0 0 0.654605 1 0.464115 2 0.535714 3 0.750000 4 0.833333 5 1.000000 8 1.000000 1 0 0.345395 1 0.535885 2 0.464286 3 0.250000 4 0.166667 Name: Survived, dtype: float64
In [177]:
dead = percent_of_live[0]
live = percent_of_live[1]
print(dead)
print(live)
SibSp 0 0.654605 1 0.464115 2 0.535714 3 0.750000 4 0.833333 5 1.000000 8 1.000000 Name: Survived, dtype: float64 SibSp 0 0.345395 1 0.535885 2 0.464286 3 0.250000 4 0.166667 Name: Survived, dtype: float64
In [203]:
dead.values
live.values
# df_dead = dead.to_frame()
# df_live = live.to_frame()
# df_dead
Out[203]:
Survived | |
---|---|
SibSp | |
0 | 0.654605 |
1 | 0.464115 |
2 | 0.535714 |
3 | 0.750000 |
4 | 0.833333 |
5 | 1.000000 |
8 | 1.000000 |
In [232]:
# 인원 수만으로 나타낸 생존자/사망자 그래프
print(sib_dead_or_live)
sns.catplot(x = 'SibSp', col = 'Survived', kind = 'count', data = titanic_df)
plt.show()
Survived SibSp 0 0 398 1 97 2 15 3 12 4 15 5 5 8 7 1 0 210 1 112 2 13 3 4 4 3 Name: Survived, dtype: int64
In [230]:
# 백분율을 이용하여 그려낸 형제자매 명수 별 생존자/사망자
# 그래프 꾸미기
plt.show()
plt.xlabel("Sibling")
plt.ylabel('%')
plt.title("sibling vs Survived")
# 그래프 그리기
plt.plot(dead.values, label = "dead")
plt.plot(live.values, label = "live")
plt.legend()
plt.show()
형제자매수가 많을 수록 타이타닉호에서 사망률이 높은 것을 알 수 있었음.
'전문지식 함양 > TIL' 카테고리의 다른 글
[프로그래머스 겨울방학 인공지능 과정] EDA Project2 (0) | 2022.01.15 |
---|---|
[프로그래머스 겨울방학 인공지능 과정] EDA Project1 (0) | 2022.01.14 |
[프로그래머스 겨울방학 인공지능 과정] FLASK 실습 (0) | 2022.01.13 |
[프로그래머스 겨울방학 인공지능 과정] Flask with REST API (0) | 2022.01.11 |
[프로그래머스 겨울방학 인공지능 과정] Flask 기초 (0) | 2022.01.10 |