728x90

1. EDA 소개

https://www.kaggle.com/code/ash316/eda-to-prediction-dietanic/notebook

이번에 필사할 EDA는 EDA To Prediction(DieTanic)이다.

Import 할 라이브러리

import numpy as np 
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use('fivethirtyeight') 
import warnings
warnings.filterwarnings('ignore')
%matplotlib inline

2. EDA 필사

1) 데이터 불러오기 및 확인

data = pd.read_csv('./titanic.csv')
print(data.isnull().sum())
data.head()

data.isnull()을 하면 결측치(null인 항목)에 대해 True를 반환한다.
이후 data.isnull().sum()을 통해 결측치의 개수를 구할 수 있다.
(True는 1, False는 0으로 취급하기 때문)
.head() 메소드를 사용하면 상위 5행을 출력한다.

2) 생존자 시각화 (Class 분포 확인)

f, ax = plt.subplots(1, 2, figsize = (18,8))
data['Survived'].value_counts().plot.pie(explode = [0,0.1], autopct = '%1.1f%%',ax = ax[0],shadow = True)
ax[0].set_title('Survived')
ax[0].set_ylabel('')
sns.countplot(x = 'Survived',data = data, ax = ax[1])
ax[1].set_title('Survived')
plt.show()

일단 subplots를 활용해서 그래프 두개를 만들었다.
ax[0]에는 pie plot을, ax[1]에는 countplot을 만들었다.
제시된 코드에서 위에서 5번째 줄에 오류가 있어서 수정을 했다.
.value_counts() 라는 함수는 처음봤는데 이 함수는 기본적으로 지정된
열의 각 값(value)에 대한 모든 발생 횟수를 반환한다.
즉, unique value를 반환한다.

3) Feature와 Class 관계 파악하기

1. 성별과 생존과의 관계

#성별과 생존과의 관계
f, ax = plt.subplots(1,2,figsize=(18,8))
data[['Sex','Survived']].groupby(['Sex']).mean().plot.bar(ax = ax[0]) 
ax[0].set_title('Survived vs Sex')
sns.countplot(x = 'Sex',hue = 'Survived',data = data, ax = ax[1])
ax[1].set_title('Sex:Survived vs Dead')
plt.show()

위의 코드에서 3번째 줄은 data에서 ‘Sex’, ‘Survived’ 열에 대해서 ‘Sex’에 대해 생존 여부로 그룹화를 시킨다. 따라서 성별에 따라 생존여부가 합쳐져서 나왔을 것이다.
예를 들어, 아래의 코드로 남성 109명 생존, 여성 233명 생존함을 확인할 수 있다.
여기에 .mean() 함수로 평균을 표현할 수 있다.

data[['Sex','Survived']].groupby(['Sex']).sum()
#결과는 아래의 표와 같다
  Survived
Sex  
female 233
male 109

groupby()

https://www.w3resource.com/w3r_images/pandas-groupby-split-apply-combine.svg

groupby(): 데이터를 그룹별로 분할해서 독립된 그룹에 대해 별도로 데이터를 처리(또는 적용)하거나 그룹별 통계량을 확인하고자 할 때 유용한 함수이다. 3가지 단계로 나뉜다.

  1. Split 단계 : .groupby() 에서 정의한 칼럼 조건에 따라 독립된 그룹으로 나눠준다.
    예시에서는 ID값을 기주느로 나누었다.
  2. Apply 단계 : 독립된 그룹별 함수를 적용하는 단계. 예시에서는 sum 함수를 활용해서
    각 그룹별 총계가 합산된 결과를 확인할 수 있다.
  3. Combine 단계 : 최종 단계로, 각각 독립된 그룹별로 함수가 적용된 결과를 다시
    하나로 종합해서 다시 하나의 테이블로 합친다.

.agg()에 적용할 수 있는 통계함수

count 데이터의 개수
sum 합계
mean 평균
median 중앙값
var, std 분산, 표준편차
min, max 최소, 최대값
unique, nunique 고유값, 고유값 개수
prod
first, last 첫째, 마지막값
data.groupby('Sex').agg(['mean','var'])
#위의 방법처럼 활용하면 된다. 

2. 선실 등급과 생존간의 관계

f, ax = plt.subplots(1,2,figsize=(18,8))
data['Pclass'].value_counts().plot.bar(color=['#CD7F32','#FFDF00','#D3D3D3'],ax = ax[0])
ax[0].set_title('Number Of Passengers By Pclass')
ax[0].set_ylabel('Count')
sns.countplot(x = 'Pclass',hue = 'Survived',data = data, ax = ax[1])
ax[1].set_title('Pclass:Survived vs Dead')
plt.show()

countplot의 옵션중에 hue 는 주어진 값에 따라 색을 다르게 하라는 의미이다.
첫 그래프는 Pclass에 대해서 선실 등급별로 인원수를 구하고 서로 다르게 색을 칠했다.
두번째 그래프는 countplot을 활용해서 선실 등급별로 생존/사망 인원의 총합을 구했다.

3. factorplot(catplot)

sns.factorplot('Pclass','Survived',hue='Sex',data = data)
plt.show()

위의 코드를 작성했는데 오류가 발생했다.
module 'seaborn' has no attribute 'factorplot'
… 이게머노;; 그래서 검색을 해봤더니 seaborn 패키지의 factorplot 함수는 seaborn 버전 0.11.0에서 catplot으로 이름이 변경되어서 factorplot 함수를 사용하려면 seaborn 버전을 0.10.0 이하로 다운그레이드 해야한다 카더라.
근데 굳이 다운그레이드를 할 필요성은 못느껴서(catplot이 factorplot 기반으로 더
많은 유형의 플롯을 지원하기도하고..)
그냥 catplot 함수를 사용했다.

#수정된 코드
sns.catplot(x = 'Pclass',y = 'Survived',hue='Sex',data = data)
plt.show()

Untitled

으음… 이게 머노;; 2트.. 뭔가 옵션이 바뀐게 있나 확인해봣다.
그랬더니 factorplot 함수를 catplot 함수로 변경할 때는 kind 인수를 사용하여 플롯의 유형을 명시해줘야 한다더라. catplot 함수에서 'point', 'bar', 'strip', 'swarm', 'box'
, 'violin', 'boxen', 'count' 중 하나를 kind 인수로 지정할 수 있다. 여기서 kind='point' 인수를 사용하여, factorplot에서 사용할 수 있었던 'point' 유형의 플롯을 그릴 수 있다. 만약 다른 유형의 플롯을 그리고 싶다면, kind 인수에 해당 유형의 문자열을 전달해주면 된다.

#찐찐막
sns.catplot(x = 'Pclass',y = 'Survived',hue='Sex',data = data,kind = 'point')
plt.show()
#아래의 이미지를 보면 정상적으로 출력되는 것을 확인할 수 있다.

Untitled

4) Age 공략하기

f, ax = plt.subplots(1,2,figsize=(18,8))
sns.violinplot(x = 'Pclass',y = 'Age',hue='Survived',data=data,split = True,ax = ax[0])
ax[0].set_title('Pclass and Age vs Survived')
ax[0].set_yticks(range(0,110,10))
sns.violinplot(x = 'Sex',y = 'Age',hue='Survived',data=data,split=True,ax=ax[1])
ax[1].set_title('Sex and Age vs Survived')
ax[1].set_yticks(range(0,110,10))
plt.show()

print('# of Null Values of Age Column: ', data['Age'].isnull().sum())
  1. split = True인 경우

Untitled

  1. split = False인 경우(디폴트 값)

Untitled

violinplot함수로 그래프를 그렸다. 여기서 split = True 인데 `split = True`일 경우, 범주형 변수를 기준으로 바이올린 그래프를 분할한다.
seaborn 패키지의 violinplot 함수에서 split 옵션은 True 또는 False 값을 가지며, 기본값은 False입니다. 이 옵션은 바이올린 플롯을 그릴 때, 카테고리형 데이터를 나누어서 그릴지 여부를 결정합니다.

split=False로 설정하면, 바이올린 플롯이 하나의 그래프로 그려지며, 모든 카테고리 값이 한 그래프에 나타납니다. 이때, 그래프의 왼쪽과 오른쪽에 있는 부분은 각각 해당 카테고리 값의 분포를 보여줍니다.

split=True로 설정하면, 카테고리 값에 따라 바이올린 플롯을 두 개로 나누어서 그립니다. 각 카테고리 값마다 하나의 그래프를 그리며, 두 개의 그래프가 분할된 형태로 그려집니다. 이때, 그래프의 왼쪽과 오른쪽에 있는 부분은 각각 해당 카테고리 값의 분포를 보여줍니다.

예를 들어, split=True로 설정하고 성별에 따른 나이 분포를 나타내는 바이올린 플롯을 그리면, 남성과 여성 각각에 대한 바이올린 플롯이 두 개로 나누어져서 그려집니다. 이렇게 하면, 두 그래프를 쉽게 비교할 수 있어서 더욱 직관적인 결과를 얻을 수 있습니다.

1. 이름에서 특정한 부분 추출하기

#이름에서 특정한 부분 추출하기
data['Initial'] = 0
for i in data:
    data['Initial']= data.Name.str.extract('([A-Za-z]+)\.')
data

DataFrame에 Initial이라는 열을 새로 생성했다.

위의 정규식 표현을 해석하자면 [A-Za-z]는 알파벳에 해당하는 모든 문자를
뜻한다. + 는 선행하는 문자들 1개 또는 여러개이다. 즉 알파벳 여러개이다.
이를 group operator () 로 묶어 연산자에 동시에 적용되게 했다.
뒤에는 특수문자 . 를 일반문자로 활용하기위해 \ 를 이용했다.
즉, 알파벳. 으로된 문자열을 추출해주세요~ 이런 뜻이다. 이 방법을 사용하면 Mr, Mrs, Miss를 다 찾아낼 수 있다.

뽑아낸 이니셜이 성별로 어떤 분포를 가지고 있는지 표로 살펴보자

## 뽑아낸 이니셜이 성별로 어떤 분포를 가지고 있는지 표로 살펴봅시다
pd.crosstab(data.Initial,data.Sex).T

crosstab() : crosstab() aka, 교차분석표는 범주형 데이터 2개를 비교분석할 때
유용하다. 각 범주형 데이터의 개수를 행과 열로 교차시켜놓은 표이다.
필수요소는 index , columns이다.
index : 행으로 그룹화할 값, columns : 열로 그룹화할 값이다.
선택 요소는 여기를 참고하자!

일부 오타 수정 with replace 함수

data['Initial'].replace(
['Mlle','Mme','Ms','Dr','Major','Lady','Countess','Jonkheer','Col','Rev','Capt','Sir','Don'],
['Miss','Miss','Miss','Mr','Mr','Mrs','Mrs','Other','Other','Other','Mr','Mr','Mr'],
inplace = True)
print(data.groupby('Initial')['Age'].mean())#평균값 확인!

replace() : 바꿀 값과 대체할 값을 차례로 써주면 된다.
inplace = True 로 해줘야 원본 DataFrame도 수정이 된다.
groupby() 로 Initial 열에 저장된 나이의 평균값을 구했다.

각 평균값에 맞게 결측치 채워주기

# 이제 각 이니셜 별로 평균 나이를 알아냈으니, 각 평균값에 맞게 채워줍니다.
#loc 활용하기!
data.loc[(data.Age.isnull())&(data.Initial=='Mr'),'Age'] = 33
data.loc[(data.Age.isnull())&(data.Initial=='Mrs'),'Age'] = 36
data.loc[(data.Age.isnull())&(data.Initial=='Master'),'Age'] = 5
data.loc[(data.Age.isnull())&(data.Initial=='Miss'),'Age'] = 22
data.loc[(data.Age.isnull())&(data.Initial=='Other'),'Age'] = 46

print('결측치 제거 후 남은 결측치: ',data.Age.isnull().sum())

loc[ , ] 에서 콤마(,) 앞 뒤에는 하나의 레이블, 레이블들의 list, 레이블들의 slice, 조건 연산자, 콜론(:) (모든 열/행 의 값) 등이 올 수 있다.
위의 코드에서도 loc 을 활용해서 Age값이 결측치이면서 Initial열에 따라 평균 나이를 삽입한다. 즉 3번째 문장을 해석하자면 Age 값이 null 이고 Initial 열이 ‘Mr’인 행들에 대해서 ‘Age’ 열에 33을 저장하라는 뜻이다.

최종 생존여부 별 연령대 확인

f, ax = plt.subplots(1,2,figsize=(20,10))
data[data['Survived']==0].Age.plot.hist(ax=ax[0],bins=20,edgecolor='black',color='red')
ax[0].set_title('Survived=0')
x1 = list(range(0,85,5))
ax[0].set_xticks(x1)
data[data['Survived']==1].Age.plot.hist(ax=ax[1],color = 'green',bins=20,edgecolor='black')
ax[1].set_title('Survived=1')
x2=list(range(0,85,5))
ax[1].set_xticks(x2)
plt.show()

첫번째 그래프는 ‘Survived’ 열이 0인 즉, 사망한 사람들의 나이를 히스토그램으로 그리라는 뜻이다. 여기서 옵션들이 추가되었는데 bins 옵션은 bin의 개수를 지정하는 것으로 bin은 막대그래프이다. 또한,set_xticks() 함수는 x축에 표시될 눈금의 위치를 설정하는 함수이다. 즉, x축에 표시될 틱(tick)의 위치를 지정할 수 있습니다. 따라서 x1은 0부터 85까지 5씩 증가하는 리스트이고 이게 x축에 반영이 되었다.

Untitled

5) 탑승 항구와 생존여부

sns.catplot(x='Embarked',y='Survived',data=data,kind='point')
fig=plt.gcf()
fig.set_size_inches(5,3)
plt.show()

아까와 동일하게 factorplot을 catplot으로 수정했다.
gcf() : Get the current figure 라는 뜻으로 현재 figure를 가져오는데 사용된다.
만약 현재 figure가 존재하지 않으면 하나가 생성된다.
set_size_inches() : figure의 사이즈를 설정하는 함수이다. 자세하게는 set figure width and height in inches이다.

f,ax=plt.subplots(2,2,figsize=(20,15))
sns.countplot(x='Embarked',data=data,ax=ax[0,0])
ax[0,0].set_title('No. Of Passengers Boarded')
sns.countplot(x='Embarked',hue='Sex',data=data,ax=ax[0,1])
ax[0,1].set_title('Male-Female Split for Embarked')
sns.countplot(x='Embarked',hue='Survived',data=data,ax=ax[1,0])
ax[1,0].set_title('Embarked vs Survived')
sns.countplot(x='Embarked',hue='Pclass',data=data,ax=ax[1,1])
ax[1,1].set_title('Embarked vs Pclass')
plt.subplots_adjust(wspace=0.2,hspace=0.5)
plt.show()

2x2 크기로 여러 개의 그래프를 그렸다. 그래프들은 탑승항구를 기반으로 그렸다.
첫 그래프는 탑승 항구별 탑승 인원을 countplot으로 그렸다.
두번째 그래프는 탑승 선착장별로 성별로 탑승 인원을 구분했다.
세번째 그래프는 탑승 선착장별로 생존 여부를 표현햇다.
마지막 그래프는 탑승 선착장별로 객실 등급을 표현했다.
subplots_adjust로 그래프 사이의 좌우 간격을 조정했다.

sns.catplot(x='Pclass',y='Survived',hue='Sex',col='Embarked',data=data,kind='point')
plt.show()

hue를 통해 성별에 따라 객실 등급을 표시하였고 col 옵션에 ‘Embarked’를 줘서 탑승 선착장별로 3가지 그래프를 그렸다.
이를 통해 가장 많은 승객이 탑승한 선착장은 S이고 대부분 3등급 객실이라는 것을
알수있다. 마지막 그림에서 S 선착장에서 알아낼 수 있는 사실은 여성 탑승객들의 생존율이 매우 높지만 1등급 객실의 남성과 3등급 객실의 여성의 생존율에 큰 차이가 없다는 사실이다.

'인공지능 > 인공지능 기초 개념' 카테고리의 다른 글

(1)-2 Pandas 실습  (1) 2024.03.15
(3)-2 EDA 실습  (1) 2024.03.15
(3)EDA  (0) 2024.03.15
(2) 데이터 시각화  (1) 2024.03.14
(1) Pandas란?  (0) 2024.03.14

+ Recent posts