赞
踩
泰坦尼克号数据集为1912年泰坦尼克号撞击冰山沉没事件中一些乘客和船员的个人信息及是否幸存的状况。可利用该数据进行分析,挖掘数据中有用的信息。
<本文是学习《R语言统计分析与机器学习》后的学习笔记>
数据概况:
该数据集中,训练数据集包含891个样本,共有12个特征,测试数据集包含418个样本,11个特征。两个数据集的原始数据中包含很多缺失值,或不能直接用于分析的信息。故我们需要对其进行预处理,便于挖掘分析。
library(readr)
library(VIM)
library(caret)
library(rpart)
library(rpart.plot)
library(Metrics)
library(ROCR)
library(readxl)
library(stringr)
library(ggplot2)
## 读取训练集和测试集
Ttrain <- read_csv("C:/Mathmodel/Titanic train.csv")
Ttest <- read_csv("C:/Mathmodel/Titanic test.csv")
##查看训练集和测试集的数据形式
dim(Ttrain)
colnames(Ttrain)
dim(Ttest)
colnames(Ttest)
## 组合数据(其中Ttrain[,-2]指删除训练集Ttrain第二列数据
Alldata <- rbind.data.frame(Ttrain[,-2],Ttest)
##上面这样就是按行将两个数据集拼接在一起
summary(Alldata)#可利用summary观察数据情况
Survived <- Ttrain$Survived
table(Survived)
运行结果
> dim(Ttrain)#训练集维度
891 12
> colnames(Ttrain)#指标名称
"PassengerId" "Survived" "Pclass" "Name" "Sex" "Age" "SibSp" "Parch" "Ticket" "Fare" "Cabin" "Embarked"
> dim(Ttest)#测试集维度
418 11
> colnames(Ttest)#指标名称
"PassengerId" "Pclass" "Name" "Sex" "Age" "SibSp" "Parch" "Ticket" "Fare" "Cabin" "Embarked"
##可发现训练集和测试集之间,测试集没有指标Survived
> Survived <- Ttrain$Survived
> table(Survived)
Survived
0 1
549 342
利用summary观察数据情况结果如下
> summary(Alldata)
PassengerId Pclass Name Sex
Min. : 1 Min. :1.000 Length:1309 Length:1309
1st Qu.: 328 1st Qu.:2.000 Class :character Class :character
Median : 655 Median :3.000 Mode :character Mode :character
Mean : 655 Mean :2.295
3rd Qu.: 982 3rd Qu.:3.000
Max. :1309 Max. :3.000
Age SibSp Parch Ticket
Min. : 0.17 Min. :0.0000 Min. :0.000 Length:1309
1st Qu.:21.00 1st Qu.:0.0000 1st Qu.:0.000 Class :character
Median :28.00 Median :0.0000 Median :0.000 Mode :character
Mean :29.88 Mean :0.4989 Mean :0.385
3rd Qu.:39.00 3rd Qu.:1.0000 3rd Qu.:0.000
Max. :80.00 Max. :8.0000 Max. :9.000
NA's :263
Fare Cabin Embarked
Min. : 0.000 Length:1309 Length:1309
1st Qu.: 7.896 Class :character Class :character
Median : 14.454 Mode :character Mode :character
Mean : 33.295
3rd Qu.: 31.275
Max. :512.329
NA's :1
从输出结果我们可看出:训练数据集中存活下来的人数有342人,遇难人数有549人。
数据中的特征有:
乘客ID(passengerId),是否获救(Survived),乘客分类(Pclass),姓名(Name),性别(Sex),年龄(Age),有多少兄弟姐们/配偶同船(Parch),票号(Ticket),票价(Fare),客舱号(Cabin),出发港口(Embarked)。
aggr(Alldata)
得到缺失值分布图,结果如下
由上图可发现,Cabin变量的缺失值已经超过70%,所以该变量可以直接剔除,Age的缺失值也较多,且Fare和Embarked变量也有较少部分的缺失值。
## Cabin缺失值太多,可以直接剔除
Alldata$Cabin <- NULL
## 船票和ID具有识别性所以需要剔除
Alldata$PassengerId <- NULL
Alldata$Ticket <- NULL
其中Cabin变量因为缺失值过多,直接删除更好,而PassengerID和Ticket都可以直接对应到乘客个体,所以需要剔除。
对于其他的具有缺失值的变量,使用简单的缺失值填补方法。`
## 年龄变量的缺失值可以使用中位数来填补
Alldata$Age[is.na(Alldata$Age)] <- median(Alldata$Age,na.rm = TRUE)
## fare变量的缺失值可以使用均值来填补
Alldata$Fare[is.na(Alldata$Fare)] <- mean(Alldata$Fare,na.rm = TRUE)
## Embarked变量的缺失值,可以使用众数来填补
Embarkedmod <- names(sort(table(Alldata$Embarked),decreasing = T)[1])
Alldata$Embarked[is.na(Alldata$Embarked)] <- Embarkedmod
上面程序分别使用了中位数,平均值,众数来填补这三个变量的特征。
## 获取新的特征,提取name变量中的特征
newname <- str_split(Alldata$Name," ")
newname <- sapply(newname, function(x) x[2])
sort(table(newname),decreasing = T)
> sort(table(newname),decreasing = T)
newname
Mr. Miss. Mrs. Master. Dr. Rev.
736 256 191 59 8 8
y Col. Planke, Billiard, Impe, Carlo,
8 4 4 3 3 2
Gordon, Major. Messemaeker, Mlle. Ms. Brito,
2 2 2 2 2 1
Capt. Cruyssen, der Don. Jonkheer. Khalil,
1 1 1 1 1 1
Melkebeke, Mme. Mulder, Palmquist, Pelsmaeker, Shawah,
1 1 1 1 1 1
Steen, the Velde, Walle,
1 1 1 1
针对Name变量,因为名称中主要包含的称谓为Mr,Miss,Mrs,Master等,所以可将该特征转化为新的特征,即保留Mr,Miss,Mrs,Master四种称呼,其余使用other代替。
## 名字设置为 Mr. Miss. Mrs. Master. ,其余的使用other代替
newnamepart <- c("Mr.","Miss.","Mrs.","Master.")
newname[!(newname %in% newnamepart)] <- "other"
Alldata$Name <- as.factor(newname)
Alldata$Sex <- as.factor(Alldata$Sex)
Alldata$Embarked <- as.factor(Alldata$Embarked)
summary(Alldata)
str(Alldata)
结果如下:
> summary(Alldata)
Pclass Name Sex Age SibSp
Min. :1.000 Master.: 59 female:466 Min. : 0.17 Min. :0.0000
1st Qu.:2.000 Miss. :256 male :843 1st Qu.:22.00 1st Qu.:0.0000
Median :3.000 Mr. :736 Median :28.00 Median :0.0000
Mean :2.295 Mrs. :191 Mean :29.50 Mean :0.4989
3rd Qu.:3.000 other : 67 3rd Qu.:35.00 3rd Qu.:1.0000
Max. :3.000 Max. :80.00 Max. :8.0000
Parch Fare Embarked
Min. :0.000 Min. : 0.000 C:270
1st Qu.:0.000 1st Qu.: 7.896 Q:123
Median :0.000 Median : 14.454 S:916
Mean :0.385 Mean : 33.295
3rd Qu.:0.000 3rd Qu.: 31.275
Max. :9.000 Max. :512.329
此时Alldata数据形式,已转化为因子变量
> str(Alldata)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 1309 obs. of 8 variables:
$ Pclass : num 3 1 3 1 3 3 1 3 3 2 ...
$ Name : Factor w/ 5 levels "Master.","Miss.",..: 3 4 2 4 3 3 3 1 4 4 ...
$ Sex : Factor w/ 2 levels "female","male": 2 1 1 1 2 2 2 2 1 1 ...
$ Age : num 22 38 26 35 35 28 54 2 27 14 ...
$ SibSp : num 1 1 0 1 0 0 0 3 0 1 ...
$ Parch : num 0 0 0 0 0 0 0 1 2 0 ...
$ Fare : num 7.25 71.28 7.92 53.1 8.05 ...
$ Embarked: Factor w/ 3 levels "C","Q","S": 3 1 3 3 3 2 3 3 3 1 ...
上面的程序在处理好Name特征后,将Name,Sex,Embarked等特征转换为因子变量。最终数据集中就有3个因子变量和5个数值变量。
## 与处理好的训练数据和测试数据分开
Ttrainp <- Alldata[1:nrow(Ttrain),]
Ttrainp$Survived <- Survived
Ttestp <- Alldata[(nrow(Ttrain)+1):nrow(Alldata),]
str(Ttrainp)
write.csv(Ttrainp,"data/chap9/Titanic_clean.csv",row.names = F)
上面的程序是将处理好的数据重新切分为训练数据集和测试数据集,并将新训练数据集写入csv文件。
## 切分训练数据集为训练集和测试集,70%训练
set.seed(123)
CDP <- createDataPartition(Ttrainp$Survived,p = 0.8)
#createDataPartition()就是数据划分函数
train_data <- Ttrainp[CDP$Resample1,]
test_data <- Ttrainp[-CDP$Resample1,]
mod1 <- rpart(Survived~.,data =train_data,method="class",cp = 0.000001)#利用决策树分类器建立决策树模型
summary(mod1)
## 看变量重要性
mod1$variable.importance
#cp是每次分割对应的复杂度系数
mod1$cp
## plot cross-validation results
plotcp(mod1)
运行结果如下
> ## 看变量重要性
> mod1$variable.importance
Name Sex Fare Age Parch Pclass SibSp Embarked
111.91631 89.02461 61.63420 46.05885 38.32346 36.69987 30.46093 9.64527
> #cp是每次分割对应的复杂度系数
> mod1$cp
CP nsplit rel error xerror xstd
1 0.450549451 0 1.0000000 1.0000000 0.04754450
2 0.051282051 1 0.5494505 0.5604396 0.04015432
3 0.014652015 3 0.4468864 0.4615385 0.03730757
4 0.010989011 4 0.4322344 0.4798535 0.03787823
5 0.007326007 6 0.4102564 0.5091575 0.03874859
6 0.003663004 12 0.3589744 0.4835165 0.03798985
7 0.000001000 15 0.3479853 0.4798535 0.03787823
利用rpart.plot()函数将决策树可视化
rpart.plot(mod1, type = 2,extra="auto", under=TRUE,
fallen.leaves = FALSE,cex=0.7, main="决策树")
可发现根节点为Name变量,而且如果Name=Mr或者Other,则更倾向于划分为遇难的叶子节点。说明有更多的男性会将危险留给自己,优先让发女性和儿童逃离危险。
3.使用测试集来验证模型的预测精度
先对模型进行预测,由于得到的结果是幸存和遇难的概率,我们需要将幸存概率大于0.5的归类于幸存,小于0.5的归类于遇难,便于后面的统计分析。
pre_train <- predict(mod1,train_data,type = "prob")
pre_train2<-as.factor(as.vector(ifelse(pre_train[,2]>0.5,1,0)))
pre_test <- predict(mod1,test_data)
pre_test2<-as.factor(as.vector(ifelse(pre_test[,2]>0.5,1,0)))
此时的数据情况如下:
#pre_train代表利用模型预测出来的值,但是由于是结果概率,故需要变换。
> print(pre_train)
0 1
1 0.05882353 0.94117647
2 0.05882353 0.94117647
3 0.89085546 0.10914454
4 0.89085546 0.10914454
5 0.07692308 0.92307692
#pre_train2即为重新处理化为0,1之后的变量,0代表遇难
> print(pre_train2)
[1] 1 1 0 0 1 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 1 0
[38] 1 0 0 1 1 0 0 1 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 1 0 0
此时再计算准确度
sprintf("决策树模型在训练集精度为:%f",accuracy(train_data$Survived,pre_train2))
sprintf("决策树模型在测试集精度为:%f",accuracy(test_data$Survived,pre_test2))
## 计算混淆矩阵和模型的精度
cfm <- confusionMatrix(pre_test2,as.factor(test_data$Survived))
cfm$table
结果如下:
> sprintf("决策树模型在训练集精度为:%f",accuracy(train_data$Survived,pre_train2))
[1] "决策树模型在训练集精度为:0.866760"
> sprintf("决策树模型在测试集精度为:%f",accuracy(test_data$Survived,pre_test2))
[1] "决策树模型在测试集精度为:0.820225"
> cfm$table
Reference
Prediction 0 1
0 97 20
1 12 49
可以发现,在训练集上决策树模型的精度为86.6760%,在测试集上决策树模型的精度为82.0225%。程序中还有32个样本归类错误,精度有待改进。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。