Search code examples
rtime-seriespurrrholtwinters

HoltWinters function works fine when used by itself with purrr:map but not when used in an ifelse function


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?


Solution

  • 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)
        }
    })