Kaggle·데이터분석예제

[Kaggle][답]타이타닉(titanic)

데이터요리사 2020. 7. 20. 08:00

Titanic: Machine Learning from Disaster


1. 대회 설명

  • 키워드: #분류 # classification

  • 평가방법: 승객의 생존여부를 0, 1로 예측하여 제출하고, 정확도(accuracy)를 계산하여 순위를 결정


2. 데이터

Variable Definition Key
survival 생존여부 0 = No, 1 = Yes
pclass 티켓 등급 1 = 1st, 2 = 2nd, 3 = 3rd
sex 성별  
Age 나이  
sibsp 타이타닉에 탑승한 형제/자매 수  
parch 타이타닉에 탑승한 부모/자녀 수  
ticket 티켓번호  
fare 운임(티켓요금)  
cabin 객실 번호  
embarked 탑승한 곳(항구) C = Cherbourg, Q = Queenstown, S = Southampton

3. 데이터 전처리

데이터 훑어보기

  1. 데이터 로딩 : csv 파일을 데이터프레임으로 읽기

    train = pd.read_csv('./dataset/train.csv')
    test = pd.read_csv('./dataset/test.csv')
    submission = pd.read_csv('./dataset/gender_submission.csv')
  1. 학습 데이터 셋의 상위 5개 항목 출력

    train.head()

[결과]

  1. 학습 데이터 셋의 각 필드 데이터 분포(평균, 최소값, 최대값 등)를 살펴보기

    train.describe()

[결과]

수치형 데이터를 포함한 컬럼에 대해서만 요약 값을 출력합니다. 총 891개의 학습데이터 셋이 있고(Age값은 714개), 각 컬럼의 최소값, 최대값, 4분위수 등을 확인할 수 있습니다.

  1. 각 컬럼의 데이터 타입 확인하기

    train.info()

[결과]

```
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
```

info() 메소드를 통해 각 컬럼의 데이터 타입(Dtype)과 개수를 확인할 수 있습니다. 일부 컬럼(Age, Cabin, Embarked)은 데이터가 누락된 항목이 포함되어 있는 것 같습니다.

  1. 'Cabin'필드에는 어떤 값이 있는지 확인하기

    train['Cabin'].unique()

[결과]

```
array([nan, 'C85', 'C123', 'E46', 'G6', 'C103', 'D56', 'A6',
       'C23 C25 C27', 'B78', 'D33', 'B30', 'C52', 'B28', 'C83', 'F33',
       'F G73', 'E31', 'A5', 'D10 D12', 'D26', 'C110', 'B58 B60', 'E101',
       'F E69', 'D47', 'B86', 'F2', 'C2', 'E33', 'B19', 'A7', 'C49', 'F4',
       'A32', 'B4', 'B80', 'A31', 'D36', 'D15', 'C93', 'C78', 'D35',
       'C87', 'B77', 'E67', 'B94', 'C125', 'C99', 'C118', 'D7', 'A19',
       'B49', 'D', 'C22 C26', 'C106', 'C65', 'E36', 'C54',
       'B57 B59 B63 B66', 'C7', 'E34', 'C32', 'B18', 'C124', 'C91', 'E40',
       'T', 'C128', 'D37', 'B35', 'E50', 'C82', 'B96 B98', 'E10', 'E44',
       'A34', 'C104', 'C111', 'C92', 'E38', 'D21', 'E12', 'E63', 'A14',
       'B37', 'C30', 'D20', 'B79', 'E25', 'D46', 'B73', 'C95', 'B38',
       'B39', 'B22', 'C86', 'C70', 'A16', 'C101', 'C68', 'A10', 'E68',
       'B41', 'A20', 'D19', 'D50', 'D9', 'A23', 'B50', 'A26', 'D48',
       'E58', 'C126', 'B71', 'B51 B53 B55', 'D49', 'B5', 'B20', 'F G63',
       'C62 C64', 'E24', 'C90', 'C45', 'E8', 'B101', 'D45', 'C46', 'D30',
       'E121', 'D11', 'E77', 'F38', 'B3', 'D6', 'B82 B84', 'D17', 'A36',
       'B102', 'B69', 'E49', 'C47', 'D28', 'E17', 'A24', 'C50', 'B42',
       'C148'], dtype=object)
```
  1. 생존한 사람, 사망한 사람의 수 확인하기

    train['Survived'].value_counts()

    [결과]

    0    549
    1    342
    Name: Survived, dtype: int64
  1. 각 클래스('Pclass')별 탑승객 분포 확인하기

    train['Pclass'].value_counts().sort_index()

    [결과]

    1    216
    2    184
    3    491
    Name: Pclass, dtype: int64
  1. 성('Sex')별 탑승객 분표 확인하기
train['Sex'].value_counts().sort_index()

[결과]

female    314
male      577
Name: Sex, dtype: int64

8. 탑승 위치('Embarked') 별 탑승객 분표 확인하기

train['Embarked'].value_counts().sort_index()

[결과]

C    168
Q     77
S    644
Name: Embarked, dtype: int64

데이터 전처리

  1. null값 체크

    train.isnull().any()

    [결과]

    PassengerId    False
    Survived       False
    Pclass         False
    Name           False
    Sex            False
    Age             True
    SibSp          False
    Parch          False
    Ticket         False
    Fare           False
    Cabin           True
    Embarked        True
    dtype: bool
    train.isnull().mean()

    [결과]

    PassengerId    0.000000
    Survived       0.000000
    Pclass         0.000000
    Name           0.000000
    Sex            0.000000
    Age            0.198653
    SibSp          0.000000
    Parch          0.000000
    Ticket         0.000000
    Fare           0.000000
    Cabin          0.771044
    Embarked       0.002245

    Age, Cabin,Embarked는 null값을 포함하고 있다는 것을 확인했습니다. 'Cabin' 컬럼의 경우 null값이 차지하는 비중이 커서 데이터 분석에 활용하기에 어려울 것 같습니다.

  1. 결측치 처리(1) : 'Embarked' 필드의 결측치는 값이 가장 많은 'S'로 할당하기

    train['Embarked'] = train['Embarked'].fillna('S')
  2. 결측치 처리(2) : 'Age' 필드의 결측치는 값이 중간값으로 할당하기

    train['Age'].fillna(train['Age'].median(), inplace=True)
  1. 'Name'필드에서 신분을 나타내는 단어를 뽑아서 'Title' 필드에 할당하기

    (힌트1) : '.'을 기준으로 앞에 위치하는 문자열을 추출

    (힌트2): train['Name'].str.extract(' ([A-Za-z]+).', expand = False)

    train['Title'] = train['Name'].str.extract(' ([A-Za-z]+)\.', expand = False)
    train['Title'].unique().tolist()
  1. 'Title' 필드의 카테고리를 6개의 항목으로 변경하기

    • 'Officer': 'Capt', 'Col', 'Major', 'Dr', 'Rev'
    • 'Master' : 'Jonkheer', 'Master'
    • 'Royalty' : 'Don', 'Sir', 'the Countess', 'Lady', 'Dona'
    • 'Mrs' : 'Mme', 'Ms', 'Mrs'
    • 'Miss': 'Mlle', 'Miss'
    • 'Mr' : 'Mr'
    train['Title'] = train['Title'].replace(['Capt', 'Col', 'Major', 'Dr', 'Rev'], 'Officer')
    train['Title'] = train['Title'].replace(['Jonkheer', 'Master'], 'Master')
    train['Title'] = train['Title'].replace(['Don', 'Sir', 'the Countess', 'Lady', 'Dona'], 'Royalty')
    train['Title'] = train['Title'].replace(['Mme', 'Ms', 'Mrs'], 'Mrs')
    train['Title'] = train['Title'].replace(['Mlle', 'Miss'], 'Miss')
    
    train['Title'].value_counts()

    [결과]

    Mr          757
    Miss        262
    Mrs         200
    Master       62
    Officer      23
    Royalty       4
    Countess      1
    Name: Title, dtype: int64
  1. 변수 y를 선언해서 학습할 목표변수(=종속변수)인 'Survived'필드값을 담기
y = train['Survived']
  1. 나이('Age') 필드를 그룹핑하여 'AgeGroup'필드 생성하여 할당하기

    • 0~18세: Baby
    • 19~25세: Youth
    • 26~35세: YoungAdult
    • 36~60세: MiddleAged
    • 61~100세: Senior
    bins = [0, 18, 25, 35, 60, 100]
    group_names = ['Baby', 'Youth', 'YoungAdult', 'MiddleAged', 'Senior']
    train['AgeGroup'] = pd.cut(train['Age'], bins, labels=group_names)
    train['AgeGroup'].value_counts()

    [결과]

    YoungAdult    196
    MiddleAged    195
    Youth         162
    Baby          139
    Senior         22
    Name: AgeGroup, dtype: int64
  2. 'AgeGroup'이 'Baby'인 raw만 출력하기

    train[train['AgeGroup'] == 'Baby']

    [결과]

데이터 시각화

  1. 라이브러리 import

    import seaborn as sns
    import matplotlib.pylab as plt
  1. 학습 데이터셋(train)의 데이터 분포확인하기

    (힌트) 히스토그램 그리기, bins = 20

    train.hist(figsize=(14,14), bins=20)
    plt.show()

  1. 성별('Sex')의 생존여부('Survived') 데이터 분포확인하기 : barplot

    sns.barplot(x="Sex", y="Survived", data=train)

    [결과]

  1. 탑승 클래스('Pclass')별 + 성별('Sex') 생존여부('Survived') 데이터 분포확인하기 : barplot

    sns.barplot(x="Pclass", y="Survived", hue ='Sex', data=train)

    [결과]

  1. 전체 변수의 correlation에 대해 히트맵 그리기

    plt.subplots(figsize=(10, 10))
    sns.heatmap(train.corr(), annot=True, linewidths=.2)

    [결과]

5, 연령분포('AgeGroup')별 + 클래스('Pclass')별 생존여부('Survived') 데이터 분포확인하기: barplot

sns.barplot(x="AgeGroup", y="Survived", hue ='Pclass', data=train)

  1. 형제/자매수(''SibSp")별 + 클래스('Pclass') 별 생존여부("Survived")

    sns.barplot(x="SibSp", y="Survived",hue ='Pclass', data=train)

데이터 삭제하기(delete)

  1. 'Name', 'Ticket', 'SibSp', 'Parch', 'Cabin' , 'AgeGroup'컬럼 삭제하기

    train.drop(['Name', 'Ticket', 'SibSp', 'Parch', 'Cabin', 'AgeGroup'], axis=1, inplace=True)

텍스트 데이터 숫자 변환

from sklearn.preprocessing import LabelEncoder
label = LabelEncoder()

for col in ['Sex', 'Embarked', 'Title']:
    train[col] = label.fit_transform(train[col])

학습용, 테스트용 데이터 셋 분리하기

from sklearn.model_selection import train_test_split

x_train, x_valid, y_train, y_valid = train_test_split(train, y, test_size=0.2, random_state = 5, stratify = y)
728x90