• 在/src/main/scala上单击鼠标右键,在弹出的菜单中选择New,再在弹出的菜单中选择Scala Class,然后,在弹出的界面中,输入类的名称titanic,类型选择Object,然后回车,就可以创建一个空的代码文件titanic.scala。
删除不必要字段
• 数据集中PassengerId,Name,Ticket字段存在唯一性,三个属性意义不大,同时Cabin字段缺失值非常多,所以这四个字段不加入后续的分析:
Val df1=df.drop("PassengerId").drop("Name").drop("Ticket").drop("Cabin")
4.缺失值处理
• 统计数据集中每个字段的缺失值:
val columns=df1.columns
val missing_cnt=columns.map(x=>df1.select(col(x)).where(col(x).isNull).count)
val result_cnt=sc.parallelize(missing_cnt.zip(columns)).toDF("missing_cnt","column_name")
result_cnt.show()
• 我们观察到Age字段和Embarked字段分别存在177和2个缺失值,这里使用Age字段中所有非null的平均值来填充缺失值,使用'S'来填充Embarked字段的缺失值。
def meanAge(dataFrame: DataFrame): Double = {
dataFrame
.select("Age")
.na.drop()
.agg(round(mean("Age"), 0))
.first()
.getDouble(0)
val survived_count=df2.groupBy("Survived").count()
survived_count.show()
survived_count.coalesce(1).write.option("header", "true").csv("/home/hadoop/titanic_output/survived_count.csv")
2.不同上船港口生还情况
按上船港口以及是否存活分组计数,得到每个分组的计数,将输出结果写入本地文件。
val survived_embark=df2.groupBy("Embarked","Survived").count()
survived_embark.show()
survived_embark.coalesce(1).write.option("header", "true").csv("/home/hadoop/titanic_output/survived_embark.csv")
3.存活/未存活的男女数量及比例
val survived_sex_count=df2.groupBy("Sex","Survived").count()
val survived_sex_percent=survived_sex_count.withColumn("percent",format_number(col("count").divide(sum("count").over()).multiply(100),5));
survived_sex_percent.show()
survived_sex_percent.coalesce(1).write.option("header", "true").csv("/home/hadoop/titanic_output/survived_sex_percent.csv")
按男女性别以及是否存活分组计数,并除以总乘客数,得到每个分组的占比,将输出结果写入本地文件。
4.不同级别乘客生还人数和占总生还人数的比例
val survived_df = df2.filter(col("Survived")===1)
val pclass_survived_count=survived_df.groupBy("Pclass").count()
val pclass_survived_percent=pclass_survived_count.withColumn("percent",format_number(col("count").divide(sum("count").over()).multiply(100),5));
pclass_survived_percent.show()
pclass_survived_percent.coalesce(1).write.option("header", "true").csv("/home/hadoop/titanic_output/pclass_survived_percent.csv")
首先筛选出存活下来的乘客信息,接着按照乘客级别分组计数,然后将低级、中级、高级的人数除以总的生还人数得到比例,将输出结果写入本地文件。
5.有无同行父母/孩子的生还情况
val df4=df2.withColumn("Parch_label",when(df2("Parch")>0,1).otherwise(0))
val parch_survived_count=df4.groupBy("Parch_label","Survived").count()
parch_survived_count.show()
parch_survived_count.coalesce(1).write.option("header", "true").csv("/home/hadoop/titanic_output/parch_survived_count.csv")
加上一个Parch_label标签,如果Parch大于0则为1(有同行父母孩子),等于0则为0(无同行父母孩子)。然后根据Parch_label和是否存活分组计数,将输出结果写入本地文件。
6.按照年龄,将乘客划分为未成年人、青年人、中年人和老年人,分析四个群体生还情况
val df3=survived_df.withColumn("Age_label",when(df2("Age")<=18,"minor").when(df2("Age")>18 && df2("Age")<=35,"young").when(df2("Age")>35 && df2("Age")<=55,"middle").otherwise("older"))
val age_survived=df3.groupBy("Age_label","Survived").count()
age_survived.show()
age_survived.coalesce(1).write.option("header", "true").csv("/home/hadoop/titanic_output/age_survived.csv")
根据(3)中获得的存活乘客信息,加上一个Age_label标签,将Age中小于等于18岁的归为minor,大于18岁小于等于35岁的归为young,大于35岁小于等于55岁的归为middle,大于55岁的归为older。再根据Age_label去分组计数,将输出结果写入本地文件。
7.提取乘客等级和上船费用信息
val sef = Seq("Pclass", "Fare")
val df5 = df2.select(sef.head, sef.tail: _*)
df5.show(5)
df5.coalesce(1).write.option("header", "true").csv("/home/hadoop/titanic_output/pclass_fare.csv")
为提取的信息目标构建表头,然后根据这个表头的属性在DataFrame中筛选列,将输出结果写入本地文件。
五、 实验结果可视化
• 实验结果的可视化采用python语言,在jupyter notebook平台上运行,可视化库采用matplotlib库,同时结合pandas库、numpy库。
• 先导入需要用到的三个库:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
1.生还情况可视化
survived_count=pd.read_csv("/home/hadoop/titanic_output/survived_count.csv",dtype = {'Survived' : str})
survived_count
plt.title('Survival Count')
survived=survived_count['Survived']
count_number=survived_count['count']
bar=plt.bar(survived,count_number,width = 0.2)
bar[0].set_color('b')
bar[1].set_color('g')
plt.xlabel('Survived')
plt.ylabel("count_number")
for a, b in zip(survived, count_number):
plt.text(a, b, '%.0f' % b, ha='center', va='bottom', fontsize=8)
• 可以得知891名乘客中只有342名乘客幸存,其余549名乘客遇难丧生。
2.登船港口生存情况
survived_embark=pd.read_csv("/home/hadoop/titanic_output/survived_embark.csv",dtype = {'Survived' : str})
survived_embark
x=np.array(['0','1'])
C=survived_embark[survived_embark['Embarked']=='C']['count']
S=survived_embark[survived_embark['Embarked']=='S']['count']
Q=survived_embark[survived_embark['Embarked']=='Q']['count']
plt.bar(x,C,label='Cherbourg',width=0.2)
plt.bar(x,S,bottom=C,label='Southampton',width=0.2)
plt.bar(x,Q,bottom=S.reset_index()['count']+C.reset_index()['count'],label='Queenstown',width=0.2)
plt.legend()
• 从堆叠图中看到在南安普顿港口登船的死亡人数最多,在瑟堡登船的人存活下来的比例大,而在皇后镇登船的人较少。
3.男女性的存活情况
survived_sex_percent=pd.read_csv("/home/hadoop/titanic_output/survived_sex_percent.csv")
survived_sex_percent.set_index(['Sex','Survived'])
from matplotlib import cm
count=survived_sex_percent['count']
colors = cm.GnBu(np.arange(len(count)) / len(count))
plt.figure(figsize= (5,5))
explode = (0, 0.2, 0, 0)
plt.pie(survived_sex_percent['count'],explode=explode,autopct="%2.2f%%",colors=colors,startangle=90,labels=['female_unsurvived','female_survived','male_survived','male_unsurvived'])
• 从饼图中看到在泰坦尼克事故中,男性大部分未能存活,女性中有四分之三左右的人数得以幸存,这跟与电影中的情节一致:船上男人们让妇女儿童先逃生。
4.不同等级乘客生还情况
pclass_survived_percent=pd.read_csv("/home/hadoop/titanic_output/pclass_survived_percent.csv",dtype = {'Pclass' : str})
pclass_survived_percent
survived_number=pclass_survived_percent['count']
pclass=pclass_survived_percent['Pclass']
plt.figure(figsize= (12 ,6))
plt.subplot(121)
bar=plt.bar(pclass,survived_number,width = 0.2)
bar[0].set_color('r')
bar[1].set_color('g')
bar[2].set_color('b')
plt.xlabel('Pclass')
plt.ylabel("survived_number")
for a, b in zip(pclass, survived_number):
plt.text(a, b, '%.0f' % b, ha='center', va='bottom', fontsize=8)
plt.subplot(122)
plt.pie(survived_number,labels=pclass,autopct="%2.2f%%")
• 从柱状图和饼图来看,高级乘客占存活人数的比例最大,但同时也看到低级乘客占存活人数的人数和比例接近高级乘客。
5.有无同行父母孩子的存活情况
parch_survived_count=pd.read_csv("/home/hadoop/titanic_output/parch_survived_count.csv",dtype = {'Survived' : str,'Parch_label' : str})
parch_survived_count
plt.figure(figsize= (14 ,6))
plt.subplot(121)
label=['parch_unsurvived','no_parch_survived','no_parch_unsurvived','parch_survived']
number=parch_survived_count['count']
y=[1,2,3,4]
plt.barh(y,number,facecolor='tan',height=0.5,edgecolor='r',alpha=0.6,tick_label=label)
plt.subplot(122)
x=np.array(['0','1'])
parch=parch_survived_count[parch_survived_count['Parch_label']=='1']['count']
no_parch=parch_survived_count[parch_survived_count['Parch_label']=='0']['count']
plt.bar(x,parch,label='Parch',width=0.2)
plt.bar(x,no_parch,bottom=parch,label='no_Parch',width=0.2)
plt.legend()
• 没有同行父母孩子的存活人数多,同时看到有同行父母孩子的存活和未存活人数差不多,猜测可能是为了救自己的亲人取舍丧生。
6.不同年龄群体的存活情况
age_survived=pd.read_csv("/home/hadoop/titanic_output/age_survived.csv",dtype = {'Survived' : str})
age_survived
plt.figure(figsize= (14 ,6))
plt.subplot(121)
bar=plt.bar(age_survived['Age_label'],age_survived['count'],width = 0.3)
bar[0].set_color('r')
bar[1].set_color('b')
bar[2].set_color('g')
bar[3].set_color('orange')
plt.xlabel('Age_label')
plt.ylabel("survived_number")
for a, b in zip(age_survived['Age_label'], age_survived['count']):
plt.text(a, b, '%.0f' % b, ha='center', va='bottom', fontsize=8)
plt.subplot(122)
age=age_survived['Age_label']
number=age_survived['count']
plt.scatter(age, number, s=number*8,marker='o',c=[1,2,3,4])
• 存活人数最多的是18-35岁的年轻人,猜测可能是他们体力较好,活下来的希望大;其次是未成年人和中年人,老年人可能因为年老和体力等原因丧生较多。
7.不同等级乘客的上船费用
pclass_fare=pd.read_csv("/home/hadoop/titanic_output/pclass_fare.csv",dtype = {'Pclass' : str})
pclass_1=pclass_fare[pclass_fare['Pclass']=='1']['Fare']
pclass_2=pclass_fare[pclass_fare['Pclass']=='2']['Fare']
pclass_3=pclass_fare[pclass_fare['Pclass']=='3']['Fare']
data_to_plot=[pclass_1,pclass_2,pclass_3]
fig = plt.figure(figsize=(12,8))
plt.violinplot(data_to_plot,showmeans=True,showmedians=False)
• 从提琴图可以看到,高级乘客的平均上船费用比中级、低级用户的最高消费都高,且高级乘客甚至还有消费到500+的人,从这说明高级乘客可能比较富裕且地位高。