R语言与数据分析练习:使用ARIMA模型预测网站访问量
使用ARIMA模型预测网站访问量
一、实验背景:
随着流量的增大,某网站的数据信息量也在以一定的幅度增长
基于该网站2016年9月~2017年2月每天的访问量,使用ARIMA模型预测网站未来7天的访问量
二、实验目的:
预测网站未来7天的访问量
三、实验设计方案和流程图:
实验设计方案:
- 由于我们获取的原数据文件为sql类型的,因此我们需要将原数据文件导入mysql,再通过R语言中的方法连接mysql进行数据的读取。
- 读取数据之后,对数据进行观察。
- 观察完毕,对数据进行预处理及清洗。
- 对整理好的数据进行序列平稳性的检查:若数据平稳,则进行下一步。若数据不平稳,将进行差分运算。
- 对数据进行纯随机性检测:若数据为白噪声,则进行下一步。若数据为非白噪声,数据没有研究意义,结束实验。
- 对数据绘制BIC图进行定阶,观察平均误差的大小,获取最优的模型数值。
- 使用最优的模型,预测未来7天的网站访问量。
实验设计流程图:
四、实验过程:
1、Mysql数据导入及数据清洗
通过 Navicat Premium 将 jc_content_viewlog.sql 文件导入mysql数据库
数据清洗源代码:
# 设置工作目录并导入需要的包
setwd("D:/bigdata/R语言与数据分析/project/test1")
library("RMySQL")
library(tidyr)
library(dplyr)
library(TSA)
library(tseries)
library(forecast)
# 连接数据库 读取数据
mysqlconnection = dbConnect(MySQL(), user = 'root', password = '123456', dbname = 'rdata',
host = 'localhost')
dbSendQuery(mysqlconnection,'SET NAMES gbk')
data <- dbReadTable(mysqlconnection,'data')
# 将日期切分成年月日和时分秒
data <- separate(data = data, col = date_time, into = c("date_ymd", "date_hms"), sep = " ")
# 根据日期进行分组计数
data_Day <- aggregate(data$id, by=list(type=data$date_ymd),length)
# 保存一份训练数据 一份预测数据
dataView <- ts(data_Day[1:166, 2])
dataView1 <- ts(data_Day[1:173, 2])
2、绘制原数据的时序图与自相关图,检验序列的平稳性
# 绘制原数据的时序图和自相关图
# 结果得出原数据为不平稳数据 因此需要进行差分
plot(dataView, xlab = "时间/天", ylab = "访问量") # 绘制时序图
acf(dataView, lag.max = 200) # 绘制ACF图
# 检验序列的平稳性
adf.test(dataView) # p值大于0.05,原数据为不平稳数据
ndiffs(dataView) # 值为1,原数据为不平稳数据
# 一次差分
dataView.diff <- diff(dataView) # 进行差分
acf(dataView.diff, lag.max = 200) # 绘制差分后序列的ACF图
# 检验序列的平稳性
adf.test(dataView.diff) # p值大于0.05,原数据为不平稳数据
ndiffs(dataView.diff) # 值为1,原数据为不平稳数据
# 纯随机性检验
Box.test(dataView.diff, type = "Ljung-Box") # p值小于0.05,差分后的数据为白噪声
3、通过纯随机性检验,判断序列的价值
# 一次差分
dataView.diff <- diff(dataView) # 进行差分
acf(dataView.diff, lag.max = 200) # 绘制差分后序列的ACF图
# 检验序列的平稳性
adf.test(dataView.diff) # p值大于0.05,原数据为不平稳数据
ndiffs(dataView.diff) # 值为1,原数据为不平稳数据
# 纯随机性检验
Box.test(dataView.diff, type = "Ljung-Box") # p值小于0.05,差分后的数据为白噪声
4、绘制BIC图进行定价
# 绘制BIC图,根据BIC图定阶
# 原序列定阶
dataView.BIC <- armasubsets(y = dataView, nar = 5, nma = 5)
plot(dataView.BIC)
# 差分后的序列定阶
dataView.diff.BIC <- armasubsets(y = dataView.diff, nar = 5, nma = 5)
plot(dataView.diff.BIC)
# 初始化
checkout <- data.frame(p = 0, d = 0, q = 0, P = 0, D = 0,
Q = 0, "残差P值" = 0, "平均误差" = 0)
test_checkout <- data.frame(p = 0, d = 0, q = 0, P = 0, D = 0,
Q = 0, "残差P值" = 0, "平均误差" = 0)
# 设置行数变量 方便后期根据行号写入数据
j <- 1
# 构造一个方法
# 实现功能:根据训练数据预测结果,根据预测结果计算平均误差,
# 根据平均误差的高低,选出最优模型预测。
test_model <- function(p, q, P, Q){
model <- Arima(dataView, order = c(p, 0, q),
seasonal = list(order = c(P, 1, Q), period = 7))
result <- Box.test(model$residuals, type = "Ljung-Box")
# 预测
data_Day.forecast <- forecast(model, h = 7, level = c(99.5))
# 计算平均绝对百分误差
error <- abs(as.numeric(data_Day.forecast[[4]]) - data_Day[167:173,2]) / data_Day[167:173,2]
# 计算残差P值
p.value <- round(result$p.value, 4)
# 输出相关数据
print(paste('p=', p, ';q=', q, ';P=', P,',Q=', Q, ';残差P值:',
p.value, ';平均误差:', mean(error), collapse = ""))
test_checkout[1,1] <- p
test_checkout[1,2] <- 0
test_checkout[1,3] <- q
test_checkout[1,4] <- P
test_checkout[1,5] <- 1
test_checkout[1,6] <- Q
test_checkout[1,7] <- round(result$p.value, 4)
test_checkout[1,8] <- mean(error)
return(test_checkout)
}
# 根据BIC图,自行设定需要计算误差的p,q,P,Q
# 将参数循环传入test_model方法中
for(p in c(0,1,5)){
for(q in c(1,5)){
for(P in c(0,4,5)){
for(Q in c(1)){
test_checkout <- test_model(p, q, P, Q)
checkout[j, ] <- test_checkout[1, ]
j <- j + 1
}
}
}
}
# 将checkout数据保存到本地
write.csv(checkout, "./checkout.csv", row.names = F) # 导出每个模型的结果
选择平均误差最小的模型进行预测!
5、预测未来7天的网站访问
# 观察保存的数据,取最优模型预测
model <- Arima(dataView, order = c(1,0,1),
seasonal = list(order = c(0,1,1), period = 7))
summary(model)
# 纯随机性检验
Box.test(model$residuals, type = "Ljung-Box") # p值小于0.05,差分后的数据为白噪声
# 用训练数据,预测原数据后7天的访问量
data_Day.forecast <- forecast(model, h = 7, level = c(99.5))
# 计算平均误差
error <- abs(as.numeric(data_Day.forecast[[4]]) - data_Day[167:173,2]) / data_Day[167:173,2]
mean(error)
# 根据最优模型预测,预测未来7天的访问量
model <- Arima(dataView1, order = c(1,0,1),
seasonal = list(order = c(0,1,1), period = 7))
summary(model)
# 纯随机性检验
Box.test(model$residuals, type = "Ljung-Box") # p值小于0.05,差分后的数据为白噪声
# 预测未来7天的访问量
data_Day.forecast <- forecast(model, h = 7, level = c(99.5))
# 预测结果展示
plot(data_Day.forecast,shadecols = "oldstyle")
五、实验结论:
模型选择:
选择平均误差最小的模型进行预测,p,q,P,Q分别为1,1,0,1
预测分析:
从图预测的结果可以看出,在未来7天内,访问量总体的趋势的向上的,但是具体到每日的网站访问量先下降,然后再上升。因此最终得出网站访问量上升趋势且波动较大!