# Mean forecast
meanf <- function(x,h=10,level=c(80,95),fan=FALSE, lambda=NULL)
{
xname <- deparse(substitute(x))
n <- length(x)
if(!is.ts(x))
x <- ts(x)
start.x <- tsp(x)[1]
if(!is.null(lambda))
{
origx <- x
x <- BoxCox(x,lambda)
}
f <- ts(rep(mean(x,na.rm=TRUE),h),start=start.x,f=frequency(x))
if(fan)
level <- seq(51,99,by=3)
else
{
if(min(level) > 0 & max(level) < 1)
level <- 100*level
else if(min(level) < 0 | max(level) > 99.99)
stop("Confidence limit out of range")
}
nconf <- length(level)
lower <- upper <- matrix(NA,nrow=h,ncol=nconf)
s <- sd(x,na.rm=TRUE)
for(i in 1:nconf)
{
tfrac <- qt( 0.5 - level[i]/200, n-1)
w <- -tfrac * s*sqrt(1+1/n)
lower[,i] <- f-w
upper[,i] <- f+w
}
freq=frequency(x)
lower <- ts(lower,start=tsp(x)[2]+1/freq,f=freq)
upper <- ts(upper,start=tsp(x)[2]+1/freq,f=freq)
colnames(lower) <- colnames(upper) <- paste(level,"%",sep="")
fits <- rep(NA,n-1)
for(i in 1:(n-1))
fits[i] <- mean(x[1:i],na.rm=TRUE)
res <- x[2:n] - fits
if(!is.null(lambda))
{
fits <- InvBoxCox(fits,lambda)
x <- origx
f <- InvBoxCox(f,lambda)
lower <- InvBoxCox(lower,lambda)
upper <- InvBoxCox(upper,lambda)
}
junk <- list(method="Mean",level=level,x=x,xname=xname,mean=ts(f,start=tsp(x)[2]+1/freq,f=freq),lower=lower,upper=upper,
model=list(mu=f[1],mu.se=s/sqrt(length(x)),sd=s), lambda=lambda,
fitted =ts(c(NA,fits),start=start.x,f=freq), residuals=ts(c(NA,res),start=start.x,f=freq))
junk$model$call <- match.call()
return(structure(junk,class="forecast"))
}
thetaf <- function(x,h=10,level=c(80,95),fan=FALSE)
{
if(fan)
level <- seq(51,99,by=3)
else
{
if(min(level) > 0 & max(level) < 1)
level <- 100*level
else if(min(level) < 0 | max(level) > 99.99)
stop("Confidence limit out of range")
}
fcast <- ses(x,h=h)
tmp2 <- lsfit(0:(length(x)-1),x)$coef[2]/2
alpha <- fcast$model$par["alpha"]
n <- length(x)
fcast$mean <- fcast$mean + tmp2*(0:(h-1) + (1-(1-alpha)^n)/alpha)
fcast.se <- sqrt(fcast$model$sigma) * sqrt((0:(h-1))*alpha^2+1)
nconf <- length(level)
fcast$lower <- fcast$upper <- matrix(NA,nrow=h,ncol=nconf)
for(i in 1:nconf)
{
zt <- -qnorm( 0.5 - level[i]/200)
fcast$lower[,i] <- fcast$mean - zt*fcast.se
fcast$upper[,i] <- fcast$mean + zt*fcast.se
}
fcast$level <- level
fcast$method <- "Theta"
fcast$model <- list(alpha=alpha,drift=tmp2,sigma=fcast$model$sigma)
fcast$model$call <- match.call()
return(fcast)
}
# Random walk
rwf <- function(x,h=10,drift=FALSE,level=c(80,95),fan=FALSE,lambda=NULL)
{
xname <- deparse(substitute(x))
n <- length(x)
freq=frequency(x)
nn <- 1:h
if(!is.ts(x))
x <- ts(x)
if(!is.null(lambda))
{
origx <- x
x <- BoxCox(x,lambda)
}
if(drift)
{
fit <- summary(lm(diff(x) ~ 1))
b <- fit$coefficients[1,1]
b.se <- fit$coefficients[1,2]
s <- fit$sigma
res <- ts(c(NA,residuals(fit)))
method <- "Random walk with drift"
}
else
{
b <- b.se <- 0
s <- sd(diff(x),na.rm=TRUE)
# fits <- ts(x[-n],start=tsp(x)[1]+1/freq,f=freq)
res <- ts(c(NA,diff(x)))
method <- "Random walk"
}
tsp(res) <- tsp(x)
f <- x[n] + nn*b
se <- sqrt((nn*s^2) + (nn*b.se)^2)
if(fan)
level <- seq(51,99,by=3)
else
{
if(min(level) > 0 & max(level) < 1)
level <- 100*level
else if(min(level) < 0 | max(level) > 99.99)
stop("Confidence limit out of range")
}
nconf <- length(level)
z <- qnorm(.5 + level/200)
lower <- upper <- matrix(NA,nrow=h,ncol=nconf)
for(i in 1:nconf)
{
lower[,i] <- f - z[i]*se
upper[,i] <- f + z[i]*se
}
lower <- ts(lower,start=tsp(x)[2]+1/freq,f=freq)
upper <- ts(upper,start=tsp(x)[2]+1/freq,f=freq)
colnames(lower) <- colnames(upper) <- paste(level,"%",sep="")
fcast <- ts(f,start=tsp(x)[2]+1/freq,f=freq)
fits <- x - res
if(!is.null(lambda))
{
x <- origx
fcast <- InvBoxCox(fcast,lambda)
fits <- InvBoxCox(fits,lambda)
upper <- InvBoxCox(upper,lambda)
lower <- InvBoxCox(lower,lambda)
}
junk <- list(method=method,level=level,x=x,xname=xname,mean=fcast,lower=lower,upper=upper,
model=list(drift=b,drift.se=b.se,sd=s), fitted = fits, residuals = res, lambda=lambda)
junk$model$call <- match.call()
return(structure(junk,class="forecast"))
}
BoxCox <- function(x,lambda)
{
if(lambda < 0)
x[x < 0] <- NA
if(lambda==0)
out <- log(x)
else
out <- (sign(x)*abs(x)^lambda - 1)/lambda
if(!is.null(colnames(x)))
colnames(out) <- colnames(x)
return(out)
}
InvBoxCox <- function(x,lambda)
{
if(lambda < 0)
x[x > -1/lambda] <- NA
if(lambda==0)
out <- exp(x)
else
{
xx <- x*lambda + 1
out <- sign(xx)*abs(xx)^(1/lambda)
}
if(!is.null(colnames(x)))
colnames(out) <- colnames(x)
return(out)
}
forecast.StructTS <- function(object,h=ifelse(object$coef["epsilon"]>1e-10, 2*object$xtsp[3], 10),level=c(80,95),fan=FALSE,lambda=NULL,...)
{
xname <- deparse(substitute(x))
x <- object$data
pred <- predict(object,n.ahead=h)
if(fan)
level <- seq(51,99,by=3)
else
{
if(min(level) > 0 & max(level) < 1)
level <- 100*level
else if(min(level) < 0 | max(level) > 99.99)
stop("Confidence limit out of range")
}
nint <- length(level)
lower <- matrix(NA,ncol=nint,nrow=length(pred$pred))
upper <- lower
for(i in 1:nint)
{
qq <- qnorm(0.5*(1+level[i]/100))
lower[,i] <- pred$pred - qq*pred$se
upper[,i] <- pred$pred + qq*pred$se
}
colnames(lower) = colnames(upper) = paste(level,"%",sep="")
if(is.element("seas",names(object$coef)))
method <- "Basic structural model"
else if(is.element("slope",names(object$coef)))
method <- "Local linear structural model"
else
method <- "Local level structural model"
fits <- x - residuals(object)
if(!is.null(lambda))
{
fits <- InvBoxCox(fits,lambda)
x <- InvBoxCox(x,lambda)
pred$pred <- InvBoxCox(pred$pred,lambda)
lower <- InvBoxCox(lower,lambda)
upper <- InvBoxCox(upper,lambda)
}
return(structure(list(method=method,model=object,level=level,mean=pred$pred,lower=lower,upper=upper,
x=x,xname=xname,fitted=fits,residuals=residuals(object)),
class="forecast"))
}
forecast.HoltWinters <- function(object,h=ifelse(frequency(object$x)>1,2*frequency(object$x),10),level=c(80,95),fan=FALSE,lambda=NULL,...)
{
xname <- deparse(substitute(x))
x <- object$x
pred <- predict(object,n.ahead=h,prediction.interval=TRUE,level=level[1]/100)
pmean <- pred[,1]
if(fan)
level <- seq(51,99,by=3)
else
{
if(min(level) > 0 & max(level) < 1)
level <- 100*level
else if(min(level) < 0 | max(level) > 99.99)
stop("Confidence limit out of range")
}
nint <- length(level)
upper <- lower <- matrix(NA,ncol=nint,nrow=length(pred[,1]))
se <- (pred[,2]-pred[,3])/(2*qnorm(0.5*(1+level[1]/100)))
for(i in 1:nint)
{
qq <- qnorm(0.5*(1+level[i]/100))
lower[,i] <- pmean - qq*se
upper[,i] <- pmean + qq*se
}
colnames(lower) = colnames(upper) = paste(level,"%",sep="")
if(!is.null(lambda))
{
object$fitted[,1] <- InvBoxCox(object$fitted[,1],lambda)
x <- InvBoxCox(x,lambda)
pmean <- InvBoxCox(pmean,lambda)
lower <- InvBoxCox(lower,lambda)
upper <- InvBoxCox(upper,lambda)
}
return(structure(list(method="HoltWinters", model=object, level=level,
mean=pmean, lower=lower, upper=upper,
x=x, xname=xname, fitted=object$fitted[,1], residuals=residuals(object)),
class="forecast"))
}
## CROSTON
croston <- function(x,h=10,alpha=0.1)
{
if(sum(x<0) > 0)
stop("Series should not contain negative values")
out <- croston2(x,h,alpha)
out$x <- x
out$xname <- deparse(substitute(x))
out$residuals <- x-out$fitted
out$method <- "Croston's method"
return(structure(out,class="forecast"))
}
croston2 <- function(x,h=10,alpha=0.1,nofits=FALSE)
{
x <- as.ts(x)
y <- x[x>0]
tt <- diff(c(0,(1:length(x))[x>0]))
if(length(y)==1 & length(tt)==1)
return(rep(y/tt,h))
else if(length(y)<=1 | length(tt)<=1)
return(rep(NA,h))
y.f <- forecast(HoltWinters(y,beta=FALSE,gamma=FALSE,alpha=alpha),h=h)
p.f <- forecast(HoltWinters(tt,beta=FALSE,gamma=FALSE,alpha=alpha),h=h)
freq <- frequency(x)
tsp.x <- tsp(x)
if (!is.null(tsp.x))
{
start.f <- tsp.x[2] + 1/tsp.x[3]
freq.x <- tsp.x[3]
}
else
{
start.f <- length(x) + 1
freq.x <- 1
}
ratio <- ts(y.f$mean/p.f$mean,start=start.f, f = freq.x)
if(nofits)
return(ratio)
else
{
n <- length(x)
junk <- x*NA
for(i in 1:(n-1))
junk[i+1] <- croston2(x[1:i],h=1,alpha=alpha,nofits=TRUE)
return(list(mean = ratio, fitted = junk, model=list(demand=y.f,period=p.f)))
}
}
snaive <- function(x,h=2*frequency(x),level=c(80,95),fan=FALSE, lambda=NULL)
{
forecast(Arima(x,seasonal=list(order=c(0,1,0),period=frequency(x)), lambda=lambda),h=h,level=level,fan=fan)
}
naive <- function(x,h=10,level=c(80,95),fan=FALSE, lambda=NULL)
{
forecast(Arima(x,order=c(0,1,0),lambda=lambda),h,level=level,fan=fan)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.