2022-11-28第五章回归分析

使用lm()函数建立多元线性回归模型,使用glm()建立广义线性回归模型。

1. 青少年赌博情况数据集

# 加载包
library(faraway)
library(ggcorrplot)
library(ggplot2)

# 加载数据
data(teengamb)
head(teengamb)
teengamb数据集
# 建立回归模型
## 一元线性回归模型
lm1 <- lm(gamble~income,data = teengamb)
summary(lm1)

ggplot(teengamb,aes(x = income,y = gamble)) +
    theme_bw() +
    geom_point()
一元线性回归结果
## 探索各个变量之间的相关性
gamble_cor <- cor(teengamb)
ggcorrplot(gamble_cor,method = "square",lab = TRUE)+ # square表示矩形热图,lab=TRUE表示添加相关系数
    theme(axis.text.x = element_text(size = 10),
         axis.text.y = element_text(size = 10))

## 多元线性回归模型
lm1 <- lm(gamble~sex+income+verbal,data = teengamb)
summary(lm1)

## 剔除无关变量后的多元线性回归模型
lm2 <- lm(gamble~sex+income,data = teengamb)
summary(lm2)
## sex和income跟gamble相关性更强
变量之间的相关性热图

多元线性回归结果
# 利用所有变量进行逐步回归
## 分为训练集和测试集
set.seed(12)
index <- sample(nrow(teengamb),round(nrow(teengamb)*0.7))
train <- teengamb[index,]
test <- teengamb[-index,]
teengamblm <- lm(gamble~.,data = train)
summary(teengamblm)
## 预测回归模型
library(Metrics)
prelm <- predict(teengamblm,test)
sprintf("均方根误差为:%f",mse(test$gamble,prelm))
# '均方根误差为:322.534961'

## 使用step()函数进行逐步回归
gamblestep <- step(teengamblm,direction = "both")
summary(gamblestep)

prestep <- predict(gamblestep,test)
sprintf("均方根误差:%f",mse(test$gamble,prestep))
## 逐步回归后的均方根误差反而增大了,Adjusted R-squared值有稍许增加,
## 说明逐步回归的结果相比之前的模型结果并没有很好的提升

# Logistic回归模型
## 在训练集上使用所有变量进行逻辑回归
teengamblm <- glm(sex~.,data = teengamb,family = "binomial")
## 对逻辑回归模型进行逐步回归,来筛选变量
teengambstep <- step(teengamblm,direction = "both")
summary(teengambstep)
逻辑回归模型结果

2. Adult收入数据集

基于美国人口adult数据集R语言分析实战

# 数据处理
## 读取数据
## 因为含有字符型变量,所以为了回归分析,需要把变量变为因子变量
adult <- read.csv("adult.csv",header = F,stringsAsFactors = T)
head(adult)

## 添加变量名
colname<-c("age","workclass","fnlwgt","education","education.num",
           "marital.status","occupation","relationship",
           "race","sex","capital.gain","capital.loss","hours.per.week",
           "native.country","class")
colnames(adult)<-colname
## 查看各变量类型
str(adult)

数据集

table()函数--R语言

## 缺失值识别
sum(is.na(adult))
## 判断是否存在非NA型的缺失值情况
## table()函数统计每个因子的频数
table(adult$workclass,exclude = NULL)
缺失值识别
## 缺失值处理
## ?字符前面有一个空格
## 可以看到结果当中还有?这一项,再找找有没有更合适的处理方法
adult$occupation[adult$occupation==" ?"] <- NA
adult$native.country[adult$native.country==" ?"] <- NA
table(adult$workclass,exclude = NULL)

## 缺失值删除
adult1 <- na.omit(adult)
nrow(adult)
nrow(adult1)
head(adult1)
缺失值处理结果
# 可视化分析数据信息
## 相关系数热力图,只能选取数值型变量
library(dplyr)
adult_cor <- cor(adult1 %>% select(age,fnlwgt,education.num,
                                   capital.gain,capital.loss,hours.per.week))
ggcorrplot(adult_cor,method = "square",lab = TRUE)+ 
    theme(axis.text.x = element_text(size = 10),
         axis.text.y = element_text(size = 10))
相关系数热力图
## 不同教育程度的收入差异(直方图)
library(patchwork)
p1 <- ggplot(adult1,aes(x = education,fill=class)) +
    theme_bw(base_family = "STKaiti") +
    geom_histogram(stat = "count") +
    coord_flip() +
    labs(x="教育程度",y="人数",title = "不同教育程度的收入差异情况") +
    theme(axis.text.x = element_text(vjust = 0.5),plot.title = element_text(hjust = 0.5))
## geom_histogram()函数默认position="stack",show.legend=T
## x是因子变量,这里应该是stat="count",如果是数值变量,这里应该是stat="identity"
## 给了我启示,字符型变量的count不需要先计算生成一列num再绘图,
## 转换成因子变量可以直接绘图

p2 <- ggplot(adult1,aes(x = education,fill=class)) +
    theme_bw(base_family = "STKaiti") +
    geom_histogram(stat = "count",position = "fill") +
    coord_flip() +
    labs(x="教育程度",y="人数",title = "不同教育程度的收入差异情况") +
    theme(axis.text.x = element_text(vjust = 0.5),plot.title = element_text(hjust = 0.5))

options(repr.plot.width=12, repr.plot.height=6)
p1+p2+plot_layout(guides = 'collect')

## 博士和硕士的人数虽然较少,但博士和硕士学历大多数都能拿到较高的工资
不同教育程度的收入差距
## 受教育年限不同的收入差异
p1 <- ggplot(adult1,aes(x = education.num,fill=class)) +
    theme_bw(base_family = "STKaiti") +
    geom_histogram(stat = "count") +
    coord_flip() +
    labs(x="教育年限",y="人数",title = "不同教育年限的收入差异情况") +
    theme(axis.text.x = element_text(vjust = 0.5),plot.title = element_text(hjust = 0.5))

p2 <- ggplot(adult1,aes(x = education.num,fill=class)) +
    theme_bw(base_family = "STKaiti") +
    geom_histogram(stat = "count",position = "fill") +
    coord_flip() +
    labs(x="教育年限",y="人数",title = "不同教育年限的收入差异情况") +
    theme(axis.text.x = element_text(vjust = 0.5),plot.title = element_text(hjust = 0.5))

p1+p2+plot_layout(guides = 'collect')
## 接受教育的年限越长,其收入较高的可能性越大
不同教育年限的收入差异
## 不同性别的收入差异
p1 <- ggplot(adult1,aes(x = sex,fill=class)) +
    theme_bw(base_family = "STKaiti") +
    geom_histogram(stat = "count") +
    labs(x="性别",y="人数",title = "不同性别的收入差异情况") +
    theme(axis.text.x = element_text(vjust = 0.5),plot.title = element_text(hjust = 0.5))

p2 <- ggplot(adult1,aes(x = sex,fill=class)) +
    theme_bw(base_family = "STKaiti") +
    geom_histogram(stat = "count",position = "fill") +
    coord_flip() +
    labs(x="性别",y="人数",title = "不同性别的收入差异情况") +
    theme(axis.text.x = element_text(vjust = 0.5),plot.title = element_text(hjust = 0.5))

## 不同年龄的收入差异
p3 <- ggplot(adult1,aes(x = class,y = age,fill=class)) +
    theme_bw(base_family = "STKaiti") +
    geom_boxplot() +
    labs(x="收入",y="年龄",title = "不同年龄的收入差异情况") +
    theme(axis.text.x = element_text(vjust = 0.5),plot.title = element_text(hjust = 0.5))

## 不同工作时间的收入差异
p4 <- ggplot(adult1,aes(x = class,y = hours.per.week,fill=class)) +
    theme_bw(base_family = "STKaiti") +
    geom_boxplot() +
    labs(x="收入",y="工作时间",title = "不同工作时间的收入差异情况") +
    theme(axis.text.x = element_text(vjust = 0.5),plot.title = element_text(hjust = 0.5))

options(repr.plot.width=12, repr.plot.height=12)
(p1+p2)/(p3+p4)+plot_layout(guides = 'collect')
不同因素的收入差异
# Logistic回归模型对年收入进行预测
adult1$class <- factor(adult1$class,levels=c(" <=50K"," >50K"),labels=c(0,1))
## 数据集切分为训练集和测试集
index <- sample(nrow(adult1),round(nrow(adult1)*0.7))
train <- adult1[index,]
test <- adult1[-index,]
## 在训练集上使用变量进行逻辑回归
adult1train <- glm(class~.,data = train,family = "binomial")
## 逐步回归筛选变量
adult1step <- step(adult1train,direction = "both")
summary(adult1step)

3. Prostate前列腺病人的数据集

# 读取数据
data(prostate)
head(prostate)

# 多元线性回归
## 探索各个变量之间的相关性
prostate_cor <- cor(prostate)
options(repr.plot.width=6, repr.plot.height=6)
ggcorrplot(prostate_cor,method = "square",lab = TRUE)+ # square表示矩形热图,lab=TRUE表示添加相关系数
    theme(axis.text.x = element_text(size = 10),
         axis.text.y = element_text(size = 10))

## 多元线性回归模型
lm <- lm(lpsa~.,data = prostate)
summary(lm)
数据集

变量之间的相关系数热力图
# 逐步回归
lmstep <- step(lm,direction = "both")
summary(lmstep)
## Adjusted R-squared值基本没变化,但去掉了三个变量lcp,gleason,pgg45

# Ridge回归
## 加载包
library(glmnet)
## 数据集拆分为训练集和测试集
set.seed(123)
index <- sample(nrow(prostate),round(nrow(prostate)*0.7))
train <- prostate[index,]
test <- prostate[-index,]
## 数据标准化
train_s <- scale(train,center = TRUE,scale = TRUE)
test_s <- scale(test,center = TRUE,scale = TRUE)
head(train_s)
head(test_s)

## 利用训练集和cv.glmnet()函数分析模型参数的影响
lambdas <- seq(0,5,length.out = 200)
x <- train_s[,1:8]
y <- train_s[,9]
set.seed(1234)
ridge_model <- cv.glmnet(x,y,alpha=0,lambda=lambdas,nfolds = 3)
summary(ridge_model)
p1 <- plot(ridge_model)
p2 <- plot(ridge_model$glmnet.fit,"lambda",label = T)

p1+p2

## 建立ridge模型
ridge_min <- ridge_model$lambda.min
ridge_min

ridge_best <- glmnet(x,y,alpha = 0,lambda = ridge_min)
coef(ridge_best)

## 验证预测结果
test_pre <- predict(ridge_best,as.matrix(test_s[,1:8]))
sprintf("标准化后平均绝对误差为:%f",mae(test_s[,9],test_pre))
# '标准化后平均绝对误差为:0.416944'
p1

p2
# Lasso回归
set.seed(1234)
lasso_model <- cv.glmnet(x,y,alpha=1,lambda = lambdas,nfolds = 3)

plot(lasso_model)
plot(lasso_model$glmnet.fit,"lambda",label = T)

## 建立lasso模型
lasso_min <- lasso_model$lambda.min
lasso_best <- glmnet(x,y,alpha = 1,lambda = lasso_min)
coef(lasso_best)

## 验证预测结果
test_pre <- predict(lasso_best,test_s[,1:8])
sprintf("标准化后平均绝对误差为:%f",mae(test_s[,9],test_pre))
# '标准化后平均绝对误差为:0.421402'

日常废话:这章内容好多啊,包括很多公式推导,还得好好消化一番~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容