1912年英国白星航运公司下辖的巨轮泰坦尼克号,在从南安普敦驶向美国纽约的途中与一座冰山相撞,造成右舷船艏至船舯部破裂,五座水密舱进水。最终泰坦尼克船体断裂成两截后沉入大西洋底3700米处,2224名船员及乘客中,逾1500人丧生。
本文将和大家一起穿越百年,再回到泰坦尼克号沉船事故发生的现场。看看你我是否能成为这场灾难的幸存者?
本文采用真实数据,数据来源于 kaggle
本次训练数据,采用泰坦尼克号中891名乘客的人口学数据和基本信息。 测试数据,采用泰坦尼克号中其余418名乘客的数据
In [1]:
# 引用数据分析需要使用的一些包
# 数据规整化
import pandas as pd
from pandas import Series,DataFrame
from collections import Counter
import numpy as np
import re
# 数据可视化
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('whitegrid')
%matplotlib inline
# 机器学习
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC, LinearSVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
In [2]:
# 读取数据集
titanic_data = pd.read_csv('train.csv')
titanic_test_data = pd.read_csv('test.csv')
titanic_data.head()
Out[2]:
数据中包含的信息:
In [3]:
# 查看数据的整体信息
titanic_data.info()
In [4]:
# 查看数据的摘要信息
titanic_data.describe()
Out[4]:
从整体信息与摘要信息中我们获得了什么?
In [5]:
fig = plt.figure(figsize=(5,4), dpi=120)
ax = fig.add_subplot(111)
ax = sns.countplot('Survived',data=titanic_data,hue='Sex')
In [8]:
titanic_data = titanic_data.fillna(method='ffill') # 填补数据缺失值
titanic_data.groupby(['Survived','Sex']).count()[['PassengerId']]
Out[8]:
In [9]:
fig, axis1 = plt.subplots(1,1,figsize=(18,4))
titanic_data.Age = titanic_data.Age.apply(int)
average_age = titanic_data[["Age", "Survived"]].groupby(['Age'],as_index=False).mean()
ax = sns.barplot(x='Age', y='Survived', data=average_age)
这每一条冰冷的数据背后,都是一个真实存在的人。我们先聚焦这些数据背后鲜活的生命,来看看这些数据背后的故事。
泰坦尼克号中有一些比较有名气的人,让我们来看看他们在这场灾难中经历了什么?
In [10]:
# 通过姓氏查找人物数据的方法
def find_people(df,lastname):
name_list = []
for index,names in enumerate(df.Name.values):
if lastname in names.split(',')[0]:
name_list.append(df.iloc[index])
return name_list
# 找到约翰·雅各布·阿斯特四世
print(find_people(titanic_data,'Astor')) # 训练数据中的Astor
print('--------')
print(find_people(titanic_test_data,'Astor')) # 测试数据中的Astor
我们找到的第一个人,她的全名('Name字段')叫做Astor, Mrs. John Jacob,从名字中可以断定她是约翰·雅各布的妻子。 我们找到的第二个人,他的全名叫做Astor, Col. John Jacob,这个人就是我们要找的找到约翰·雅各布·阿斯特四世。
约翰·雅各布和他的妻子相差29岁,他们花了227英镑买下了两张泰坦尼克号一等舱的船票,并且在英吉利海峡的瑟堡港口登船开始蜜月之旅。然而不幸发生了,这艘巨轮将要沉没,在这场灾难中这对夫妻会有怎样的结局?
通过数据我们知道约翰·雅各布的妻子劫后余生(Survived =1),而雅各布先生本人的生还情况我们还不知道,不过我们可以通过Python机器学习来帮助我们找到故事的结局。
In [11]:
# 找到 Isidor Straus
find_people(titanic_test_data,'Straus')
Out[11]:
美国梅西百货股东Isidor Straus和他的妻子,花费了221英镑卖了泰坦尼克号的一等舱舱位。他们在南安普顿港口登船,最终生死未卜。但我们可以通过Python来看看这两位老夫妻的结局。
我们聚焦于这些冰冷数据后的鲜活个体后,我们再来看看那些在泰坦尼克号中的一家人,在灾难发生后有了怎样的变故?
In [12]:
# 寻找泰坦尼克号中的家庭
def get_family_lastname():
lname_list = []
fn = titanic_data.Name[titanic_data['SibSp'] >= 1] # 同辈亲戚人数大于1的乘客
fl = [name.split(',')[0] for name in fn.values] # 这些乘客的姓氏列表
fs = set(fl) # 对姓氏列表进行去重
# 确定为训练数据集中的家庭
for lname in fs:
if len(find_people(titanic_data,lname)) >= 2:
lname_list.append(lname)
return lname_list
# 在灾难发生后家庭成员存活状况
def family_info(family_lastname):
name_list = find_people(titanic_data,family_lastname) # 所有家庭成员
f_info = []
for i in name_list:
info = {}
info['lname'],info['fname'] = i.Name.split(',')
info['sex'] = i.Sex
info['Age'] = i.Age
info['Pclass'] = i.Pclass
info['Survived'] = i.Survived
f_info.append(info)
family_df = DataFrame(f_info) # 构建一个数组
return family_df
In [13]:
# 全部家庭的数组
all_family_df_list = []
for l in get_family_lastname():
all_family_df_list.append(family_info(l))
all_family_df = pd.concat(all_family_df_list)
In [14]:
all_family_df.head()
Out[14]:
我们先来看看有多少人和自己的家人一起登上了泰坦尼克号?
In [15]:
f_c = len(Counter(all_family_df.lname))
print('在泰坦尼克号中共有{}个家庭'.format(f_c))
family_member_count = all_family_df['fname'].groupby(all_family_df['lname']).count()
In [16]:
# 找到家庭成员最多的家庭
family_member_count[family_member_count == family_member_count.max()]
Out[16]:
在106个家庭中,其中Andersson安德森家族共有9名家族成员登船,我们来看看这个家庭在灾难中发生了什么?
In [17]:
all_family_df[all_family_df.lname == 'Andersson']
Out[17]:
Andersson家族中的一共有五个小孩子,其中有一个小男孩和四个小女孩。不幸的是这五个小孩子都在这场灾难中丧生了。他们中最小的只有两岁,最大的也不过11岁。
另外的四个大人,分别是Anders Johan夫妇和两个年轻人欧娜女士和爱德华先生。Anders Johan夫妇在这场灾难中共赴生死,而这两个年轻人活了下来。
在这场巨大的灾难中,一个九人组成的大家庭只有两个人幸运的活了下来,而其他七个只能随着泰坦尼克号坠入大西洋。
家庭的惨剧已然让我们悲伤不已,恋人之间的生离死别、阴阳相隔更是令人唏嘘感叹。在目睹了家庭的惨剧后,我们再来看看泰坦尼克号中的情侣们最后的结局!
In [18]:
r = re.compile(r'Mrs.(.*?)\(') # 通过正则表达式获取丈夫姓氏
husband_name = [] # 丈夫姓名列表
for l in all_family_df.fname:
n = r.findall(l)
if n:
n = n[0].strip()
husband_name.append(n)
In [19]:
# 排除同名的可能
def husband_and_wife(name):
haw_df = all_family_df[[True if name in n else False for n in all_family_df.fname]]
if len(haw_df) >= 2:
return haw_df
pass
In [20]:
# 判断家庭情况
def faw_situation(name):
faw = husband_and_wife(name)
faw_g_c = faw.groupby('lname').count()
faw_list = faw_g_c[faw_g_c.sex >= 2].index
faw_g_s = faw.groupby('lname').sum()
situation = []
for i in faw_list:
f_c = faw_g_c.loc[i,'Age']
s = faw_g_s.loc[i,'Survived']
if s == 0:
situation.append(('{} {} 夫妇'.format(i,name),'All dead'))
elif s == f_c:
situation.append(('{} {} 夫妇'.format(i,name),'All alive'))
else:
for p_info in find_people(titanic_data,i):
if name in p_info.Name:
if p_info.Survived == 0:
if p_info.Sex == 'female':
situation.append(('{} {} 夫妇'.format(i,name),'wife dead'))
break
else:
situation.append(('{} {} 夫妇'.format(i,name),'husband dead'))
break
if situation:
return situation
In [21]:
faw_situ_list = [] # 家庭情况列表
for n in husband_name:
if husband_and_wife(n) is not None:
if faw_situation(n):
faw_situ_list += faw_situation(n)
faw_situ_list[:5] # 只读取前5个数据
Out[21]:
In [22]:
f_df = DataFrame(faw_situ_list,columns=['family','Dead or Alive'])
f_df.groupby('Dead or Alive').count()
Out[22]:
In [23]:
fig = plt.figure(figsize=(5,4), dpi=120)
ax = fig.add_subplot(111)
ax = sns.countplot('Dead or Alive',data=f_df)
ax.set_title('Who dead in Titanic Disaster')
Out[23]:
泰坦尼克号中共有84对夫妻,其中18对夫妻共赴死亡,21对夫妻一起好了下来。
而另54对夫妻中,他们在生死的抉择中都选择让妻子活下来。问世间情为何物,直教人生死相许!