[Python]Pandasでタイタニック号の乗客データを解析する

  • 15
    いいね
  • 0
    コメント

タイタニック号の乗客データを使って以下を解析してみたいと思います。

  1. タイタニック号の乗客はどのような人たちだったのか
  2. それぞれの乗客はどのデッキにいたのか。またそれは客室の種類とどのような関係にあったのか。
  3. 乗客は主にどこから来たのか
  4. 家族連れか単身者か
  5. 沈没からの生還者にはどのような特徴があったのか
前準備

タイタニック号のデータは下記のURLのtrainからデータをダウンロードできます。
https://www.kaggle.com/c/titanic/data?train.csv

CSVの内容確認
import pandas as pd
from pandas import Series, DataFrame

titanic_df = pd.read_csv('train.csv')
titanic_df.head()

スクリーンショット 2016-10-29 12.03.02.png

  • Survived 0:亡くなった, 1:生き残った
  • Pclass 1:一等室, 2:二等室, 3:三等室
  • SibSp 0:兄弟姉妹と一緒に乗らなかった, 1:兄弟姉妹と一緒に乗った
  • Parch 0:親もしくは子供と一緒ではない, 1:親もしくは子供と一緒
  • Cabin 当時いた場所
  • Embarked 乗り込んだ港
データの内容
titanic_df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
Age            714 non-null float64
SibSp          891 non-null int64
Parch          891 non-null int64
Ticket         891 non-null object
Fare           891 non-null float64
Cabin          204 non-null object
Embarked       889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6+ KB

全部で891のデータがあるが、Cabinなどは204なのでNaNが多い事がわかります。

タイタニック号の乗客の所属

前準備
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
性別のグラフ化
sns.countplot('Sex', data=titanic_df)

スクリーンショット 2016-10-29 14.06.58.png

男性が多いことがわかります。

客室のランクで層別化
sns.countplot('Sex', data=titanic_df, hue='Pclass')

スクリーンショット 2016-10-29 14.08.59.png

男性が圧倒的に多いですが、特に三等室が多いことがわかります。

男性、女性、子供という新しい列を追加

次に子供という特徴で分けてみたいと思います。
このデータには子供という特徴がないので、16歳未満だったら子供と扱います。
子供,男性,女性を返却する関数を作ってみます。

def male_female_child(passenger):
    age, sex = passenger
    if age < 16:
        return 'child'
    else:
        return sex

この関数を使って新しい列を追加してみます

titanic_df['person'] = titanic_df[['Age', 'Sex']].apply(male_female_child, axis=1)
titanic_df

スクリーンショット 2016-10-29 14.18.45.png

プロットすると

sns.countplot('Pclass', data=titanic_df, hue='person')

スクリーンショット 2016-10-29 14.20.09.png

1等室には子供が殆どいないことがわかります。

年齢でヒストグラム

年齢で詳しくヒストグラムを書いてみます

titanic_df['Age'].hist(bins=70)

スクリーンショット 2016-10-29 14.22.25.png

高齢の方も少しいますね。

平均年齢
titanic_df['Age'].mean()
29.69911764705882

平均年齢は29歳とわかります。

personで属性化
titanic_df['person'].value_counts()
male      537
female    271
child      83
Name: person, dtype: int64

男性が多いことがわかります。

カーネル密度推定でプロット

年齢についてカーネル密度推定のプロットをしてみます。
プロットを0歳から最高齢までにする。

fig = sns.FacetGrid(titanic_df, hue='Sex', aspect=4)
fig.map(sns.kdeplot, 'Age', shade=True)
oldest = titanic_df['Age'].max()
fig.set(xlim=(0,oldest))
fig.add_legend()

スクリーンショット 2016-10-29 14.38.12.png

一つのプロットの中に性別で層別化された2つのプロットが出来ます。

乗っていた場所がどういう分布だったかを調べる

CabinはNaNが多いので、NaNを取り除く。

deck = titanic_df['Cabin'].dropna()
deck

1              C85
3             C123
6              E46
10              G6
11            C103
21             D56
23              A6
27     C23 C25 C27
31             B78
52             D33
54             B30
55             C52
61             B28
62             C83
66             F33
75           F G73
88     C23 C25 C27
92             E31
96              A5
97         D10 D12
102            D26
110           C110
118        B58 B60
123           E101
124            D26
128          F E69
136            D47
137           C123
139            B86
148             F2

これで取り除けました。
一方で、先頭のアルファベットは船の高さを記すものなので、先頭だけを取得してみたいと思います。

levels = []
for level in deck:
    levels.append(level[0])

levels
['C',
 'C',
 'E',
 'G',
 'C',
 'D',
 'A',
 'C',

これらを使って新しいデータフレームを作ります。

cabin_df = DataFrame(levels)
cabin_df.columns = ['Cabin']
cabin_df

スクリーンショット 2016-10-29 14.48.07.png

sns.countplot('Cabin', data=cabin_df, palette='winter_d', order=sorted(set(levels)))

スクリーンショット 2016-10-29 14.50.04.png

このような感じで描画できます。
ところでデータで「T」とありますが、これはGからTにいきなり飛んでいるのでTは間違いのデータだということがわかります。

cabin_df = cabin_df[cabin_df.Cabin != 'T']
sns.countplot('Cabin', data=cabin_df, palette='winter_d', order=sorted(set(cabin_df.Cabin)))

スクリーンショット 2016-10-29 14.52.32.png

これでTが抜けました

乗り込んだ場所と客室のランクの関係を調べる

sns.countplot('Embarked', data=titanic_df, hue='Pclass')

スクリーンショット 2016-10-29 14.55.43.png

乗り込んだ場所の人数と客室のランクがわかります。

Qはクイーンズタウンを表しますが、1,2等室の乗客がほとんどいないことがわかります。
おそらく、クイーンズタウンの当時の経済が悪いなどと予測がたてられます。

家族連れや単身者などの乗客の属性を調べる

新しいAloneというカラムを作ります。
ParchやSibSpというカラムがあるので、それを足し合わせて、0だったら単身者という判定をしましょう。

titanic_df['Alone'] = titanic_df.Parch + titanic_df.SibSp
titanic_df['Alone']
0       1
1       1
2       0
3       1
4       0
5       0
6       0
7       4
8       2
9       1
10      2

数字だとわかりにくいので、文字列を付与してわかりやすくしてみましょう

titanic_df['Alone'].loc[titanic_df['Alone']>0] = 'With Family'
titanic_df['Alone'].loc[titanic_df['Alone']==0] = 'Alone'
titanic_df.head()

スクリーンショット 2016-10-29 15.11.08.png

これでAloneというカラムが追加されました。

ではプロットしてみましょう

sns.countplot('Alone', data=titanic_df, palette='Blues')

スクリーンショット 2016-10-29 15.14.00.png

単身者が多いことがわかります。

タイタニック号から生還した人がどういう人だったかを調べる

Survivedに生存したかどうかが0,1で入っているので、それを文字列にする

titanic_df['Survivor'] = titanic_df.Survived.map({0:'no', 1:'yes'})
sns.countplot('Survivor', data=titanic_df, palette='Set1')

スクリーンショット 2016-10-29 15.19.02.png

生存者が少ないことがわかります。

生存率と客室のランクの関係を調べる

sns.factorplot('Pclass','Survived',data=titanic_df, order=[1,2,3])

スクリーンショット 2016-10-29 15.32.35.png

客室のランクが高いほど生存率が高いことがわかります。

女性と子供を優先的に避難させていたかどうかを調べてみましょう
sns.factorplot('Pclass', 'Survived', hue='person', data=titanic_df, order=[1,2,3], aspect=2)

スクリーンショット 2016-10-29 15.34.53.png

基本的には客室のランクが下がると生存率もさがるという事がわかります。
男性であれば、客室のランクにかかわらず生存率が下がります。

一方で女性と子供に関しては1等室と2等室の生存率が高く、あまり変わりません。
ですので、女性と子供を優先的に避難させていたことがわかります。

この記事は以下の講義のメモになります。
https://www.udemy.com/python-jp/learn/v4/content