【人工智能】数据分析与机器学习——泰坦尼克号(更新中)

1912年4月15日,泰坦尼克号在首次航行期间撞上冰山后沉没,船上共有2224名乘客和乘务人员,最终有1502人遇难。沉船导致大量伤亡的重要原因之一是,没有足够的救生艇给乘客和船员。虽然从这样的悲剧性事故中幸存下来有一定的运气因素,但还是有一定规律可循的,一些人,比如妇女、儿童和上层人士,比其他人有更高的存活可能性。泰坦尼克号事件留下了“弥足珍贵”的数据记录。如前所述,乘客的幸存率存在一定的规律,因此这些数据记录集成了Kaggle上流行的入门机器学习的数据集。同时,又由于该数据集中的记录不完整,存在缺失值、异常值等,因此也成了很典型的练习数据分析的数据集。

在这里插入图片描述

1. 预览数据

由于我们用到的数据集是CSV格式的,所以直接利用Pandas提供的read_csv()方法来读取数据即可。在将数据读取到内存之后,最好对数据进行简单的预览(使用head()方法)。预览的目的主要是了解数据表的大小、字段的名称及数据格式等。这为理解数据及后续的数据处理工作做了铺垫。
在这里插入图片描述

2. 获取该数据集的更多信息

我们还可以用shape属性和info()方法来获取该数据集的更多信息
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
从上面的输出不仅可看出每个字段的数据类型,更重要的是,还可从每个字段的计数信息看出,Cabin相比于其他字段仅有204个有效数据,数据缺失严重。

在这里插入图片描述
对于泰坦尼克幸存者数据集,我们也可以借助于热力图来查看缺失值的情况。

plt.rcParams['font.sans-serif'] = ['SimHei']  #正常显示中文标签
sns.heatmap(train_df.isnull(),cbar=False).set_title(r"缺失值热力图")

在这里插入图片描述

3. 数据分布

describe()会对所有数值型字段进行一些必要的统计:
在这里插入图片描述

细细体会describe()给出的信息,我们还能多少看到“异常值”(Outlier)的侧影。比如说,票价(Fare)的平均值为32.4美元,而中位数为14.45美元,平均值居然比中位数大很多,说明该特征分布是严重右偏的,我们又看到最大值是512.32美元,严重偏离均值和中位数,所以这个值很可能是潜在的异常值。

此外,还可从describe()的输出大致看到整个数据集的缺失值情况。比如,从count(计数)这个指标来看,多特征的个数都是981个,而年龄只有714个,这表明这个数据集中年龄字段至少有200个值是缺失的。

在这里插入图片描述

38%的乘客生存率

在这里插入图片描述

超过76%的乘客没有与父母和孩子一起旅行

在这里插入图片描述

大约31% 的乘客与亲属一起登船

在这里插入图片描述

少于1%的乘客付了高达512美元的船票费,少于1%的乘客年龄在64~80岁

在这里插入图片描述

Sex特征中有65%为男性

577➗891=0.6476

Cabin 中的count 与unique并不相等,说明有些乘客共享一个Cabin

Embarked一共有3种取值,其中从S港口登船的人最多

Ticket的特征下,有22%左右的重复值(unique=618)

在这里插入图片描述

4. 特征相关性分析与可视化

fig , [ax1,ax2,ax3] = plt.subplots(1,3,figsize=(20,5))
sns.countplot(x='Sex',hue='Survived',data=train_df,ax=ax1)
sns.countplot(x='Pclass',hue='Survived',data=train_df,ax=ax2)
sns.countplot(x='Embarked',hue='Survived',data=train_df,ax=ax3)
ax1.set_title('Sex 特征分析')
ax2.set_title('Pclass 特征分析')
ax3.set_title('Embarked 特征分析')

countplot()是“计数图”的意思。我们可将它认为是一种对某些分类进行计数的直方图。通过设置方法中的hue参数,可分标签显示不同类别。
在这里插入图片描述

女性有更大的存活率

train_df[['Sex','Survived']].groupby(['Sex'],as_index=False).mean()

在这里插入图片描述

上等舱的乘客(Plass=1)有更大的存活率

train_df[['Pclass','Survived']].groupby(['Pclass'],as_index=False).mean()

在这里插入图片描述

SipSp和Parch与Survive有相关性

train_df[['SibSp', 'Survived']].groupby(['SibSp'], as_index=False).mean().sort_values(by='Survived', ascending=False)

在这里插入图片描述

train_df[['Parch', 'Survived']].groupby(['Parch'], as_index=False).mean().sort_values(by='Survived', ascending=False)

在这里插入图片描述
还可以进行可视化分析:

fig ,ax =plt.subplots(1,2,figsize=(20,5))
sns.countplot(x='SibSp',hue='Survived',data=train_df,ax=ax[0])
sns.countplot(x='Parch',hue='Survived',data=train_df,ax=ax[1])
ax1.set_title('SibSp 特征分析')
ax2.set_title('Parch 特征分析')

在这里插入图片描述
可以看出,配偶或兄弟姐妹数量为0的人(如同Jack一样的单身汉)最多,但获救率最低,而配偶或兄弟姐妹数量为1的人群获救率相对较高,超过50%。观察Parch这个特征可以发现,情况和SibSp基本相同,在做模型特征选择时,可考虑将二者合并

Age与Survived有相关性

使用了seaborn库中的FacetGrid对象来绘制一个分面图(faceted plot),其中按照train_df数据集中的’Survived’列的值(0表示未存活,1表示存活)来分面,并在每个分面中绘制’Age’列的直方图:

g = sns.FacetGrid(train_df,col='Survived')
g.map(plt.hist, 'Age',bins=20)
plt.show()

'Age’参数指定了要绘制直方图的列,bins=20指定了直方图中条形的数量
在这里插入图片描述

密度图

此外,以上分析多是定量分析,我们还可以定性分析。这里的定性特指基于密度图进行分析。下面我们以年龄(Age)特征为例来说明:

fig,ax = plt.subplots(figsize=(20,5))
sns.kdeplot(train_df.loc[(train_df['Survived']==0),'Age'],color='gray',linestyle="--",fill=True,label='非幸存')
sns.kdeplot(train_df.loc[(train_df['Survived']==1),'Age'],color='gray',linestyle="--",fill=True,label='非幸存')
plt.title('Age 特征分布 - Survivor V.S. Not Survivor',fontsize=15)
plt.xlabel("Age(年龄)",fontsize=15)
plt.ylabel("Frequency(频度)",fontsize=15)

在这里插入图片描述
可以很明显看到,15岁以下的乘客的幸存率出现了小高峰,也就是说孩子的幸存率比较高,而对于15岁以上的乘客,幸存与否并无明显区别

箱形图

当然,我们还可以接着挖掘,看看年龄(Age)和舱位等级(Pclass)有什么关联。

# 箱型图特征分析
fig ,ax = plt.subplots(figsize=(20,5))
sns.boxplot(x = "Pclass", y = "Age", data=train_df,ax=ax)
sns.swarmplot(x="Pclass", y="Age", data=train_df,ax=ax,hue="Survived")

在这里插入图片描述
如果说舱位等级(Pclass)能在一定程度上代表社会地位的话,那么,不同Pclass下的年龄分布也不同,三个分布的**中位数(箱形图的中间线)**的关系为Pclass1 > Pclass2 > Pclass3。
社会地位高的人,年龄一般会比较大。而三等舱中人数众多,他们大多数是普通的想去美国讨生活的年轻人,年龄在20~30岁之间。

我们还用swarmplot()绘制了带分布的散点图,并用不同的颜色展示是否幸存,从图中可以看出,社会等级较高(即Pclass等级高)的人,他们的幸存率更高。

PS:从代码层面,如果想将两种不同类型的图形绘制在一起,可将它们的绘图坐标轴设置为一样的。

5. 数据清洗与预处理

前面我们已经收集了一些假设和结论,接下来清洗数据。

修正数据

丢弃Cabin 和 Ticket这两个特征(同时在训练集和测试集中丢弃)

train_df = train_df.drop(['Ticket','Cabin'], axis=1) #axis 删除的是列(axis=1)还是行(axis=0)
test_df = test_df.drop(['Ticket','Cabin'], axis=1)
combine = [train_df, test_df]

female 转换为1,male 转换为0

for dataset in combine:
    dataset['Sex'] = dataset['Sex'].map({'male': 0, 'female': 1}).astype(int)

train_df.head()

在这里插入图片描述

创建数据

Title特征

从Name特征中提取Title特征,并测试Title与Survive之间的关系

在泰坦尼克号数据集中,乘客的姓名(Name 列)通常包含了他们的称谓(如 Mr., Mrs., Miss., Master, Dr., etc.),这些称谓后面通常跟着一个点(.)和乘客的名字。由于这些称谓可能与乘客的社会地位、年龄或性别有关,它们可能包含对预测乘客生存几率有用的信息。

在数据分析和机器学习的预处理阶段,提取这些称谓并将其作为新的特征(或称为列)添加到数据集中是很常见的做法。这有助于捕捉原始数据中可能隐藏的模式或相关性,并可能提高模型的预测性能。

for dataset in combine:
    dataset['Title'] = dataset['Name'].str.extract('([A-Za-z]+)\.',expand=False)
pd.crosstab(dataset['Title'], dataset['Sex'])

使用 pandas 的 .str.extract() 方法可以很容易地从包含这些称谓的字符串中提取它们。在这个方法中,我们使用了正则表达式 ([A-Za-z]+)\. 来匹配一个或多个字母(不区分大小写),后面紧跟着一个点号(.)。正则表达式的括号 () 用于捕获匹配的文本,而 expand=False 参数确保只返回一个列
在这里插入图片描述
再将Title特征中常见的称呼用“Rare”来替代:

for dataset in combine:
    dataset['Title'] = dataset['Title'].replace(['Lady','Countess','Capt','Col','Don','Dr','Major','Rev','Sir','Jonkheer','Dona'],'Rare')
    dataset['Title'] = dataset['Title'].replace('Mlle','Miss')
    dataset['Title'] = dataset['Title'].replace('Ms','Miss')
    dataset['Title'] = dataset['Title'].replace('Mme','Mrs')
train_df[['Title','Survived']].groupby(['Title'],as_index=False).mean()

在这里插入图片描述
再将离散型的Title转化为有序的数值型:

title_mapping = {"Mr":1,"Miss":2,"Mrs":3,"Master":4,"Rare":5}
for dataset in combine:
    dataset['Title'] = dataset['Title'].map(title_mapping)
dataset['Title'] = dataset['Title'].fillna(0)
train_df.head()

在这里插入图片描述
丢弃Name 特征和PassengerId 特征

现在丢弃训练集和测试集中的Name特征,丢弃训练集的PassengerId特征

train_df = train_df.drop(['Name','PassengerId'], axis=1) #axis 删除的是列(axis=1)还是行(axis=0)
test_df = test_df.drop(['Name'], axis=1)
combine = [train_df, test_df]

在这里插入图片描述

IsAlone 特征

组合Parch和SibSp特征,创建一个新的FamilySize特征,再通过FamilySize特征创建一个名为IsAlone的特征。最后丢弃Parch、SibSp和FamilySize特征,保留IsAlone特征。

for dataset in combine:
    dataset['FamilySize'] = dataset['SibSp'] + dataset['Parch'] + 1
train_df[['FamilySize','Survived']].groupby(['FamilySize'],as_index=False).mean().sort_values(by='Survived',ascending=False)

在这里插入图片描述

  • 28
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值