I am trying to use a HoltWinters
prediction iteratively along a vector, without the use of a loop, but don't want the HoltWinters
function used on the first two. I have created a list of vectors using accumulate
:
library(purrr)
v <- c(73,77,71,73,86,87,90)
cumv <- accumulate(v,c)
Using map
across cumv
:
# Omit first two
hw1 <- map(cumv[-c(1:2)], function(x) HoltWinters(ts(x),gamma=F,alpha=0.35,beta=0.2))
> hw1[[5]]
#Holt-Winters exponential smoothing with trend and without seasonal component.
#Call:
#HoltWinters(x = ts(x), alpha = 0.35, beta = 0.2, gamma = F)
#Smoothing parameters:
# alpha: 0.35
# beta : 0.2
# gamma: FALSE
#Coefficients:
# [,1]
#a 89.605082
#b 3.246215
This
gives my desired result but doesn't include the first two iterations. I assumed using ifelse
would work fine:
# Include first two, use ifelse
hw2 <- map(cumv, function(x) ifelse(length(x)>2,HoltWinters(ts(x),gamma=F,alpha=0.35,beta=0.2),
ifelse(length(x)>1,max(x),NA)))
Now, hw2[[7]]
should have (I thought) returned an identical object to hw1[[5]]
but it doesn't.
> hw2[[7]]
#[[1]]
#Time Series:
#Start = 3
#End = 7
#Frequency = 1
# xhat level trend
#3 81.00000 77.00000 4.000000
#4 80.80000 77.50000 3.300000
#5 80.82400 78.07000 2.754000
#6 85.75192 82.63560 3.116320
#7 89.39243 86.18875 3.203686
Why is it getting messed up?
As Dason mentioned in their comment, the ifelse()
function is not the same as using if else
statements. The former returns a single value for each element of x, assuming x is a vector containing booleans, e.g.
x <- c(TRUE, TRUE, FALSE, FALSE)
ifelse (x, "A", "B")
returns [1] "A" "A" "B" "B"
For your purpose, you want to use a normal if else
construct:
hw2 <- map(cumv, function(x) {
if (length(x) > 2) {
return (HoltWinters(ts(x),gamma=F,alpha=0.35,beta=0.2))
} else if (length(x) > 1) {
return (max(x))
} else {
return (NA)
}
})