Search code examples
rtime-serieslapplyzooempty-list

Percent difference of time series list with empty element


I want to take the percent difference of a time series list, but I'm running into an error when the list contains an empty list() element.

For example, given a list myList that looks like:

set.seed(230)
zoo.Date <- as.Date("2003-02-01") + c(1, 3, 7, 9, 14) - 1
myList <- list(zoo(c(NA,rnorm(4)), zoo.Date), 
           zoo(c(rnorm(4), NA), zoo.Date), 
           list(),
           zoo(c(rnorm(2), NA, rnorm(2)), zoo.Date))

I can take the difference of each element with myList %>% lapply(function(x) diff(x))

But as soon as I try to divide by the previous element myList %>% lapply(function(x) diff(x) / lag(x, -1)), I get the error Error in attr(x, "tsp") <- c(1, NROW(x), 1) : cannot assign 'tsp' to zero-length vector.

The problem is the list() element. I could get rid of it, but I want to make sure that the fourth object in myList corresponds to the fourth object of the resulting (lagged) list. In other words, I want the output to look like:

[[1]]
2003-02-03 2003-02-07 2003-02-09 2003-02-14 
        NA  -1.431227   2.245691   0.100597 

[[2]]
2003-02-03 2003-02-07 2003-02-09 2003-02-14 
-0.9078077 12.8523189 -1.2523403         NA 

[[3]]
NA

[[4]]
2003-02-03 2003-02-07 2003-02-09 2003-02-14 
 -1.177138         NA         NA  -2.203719

Or with [[3]] as list() or NULL or something else empty.

I've tried using things like myList %>% unlist(recursive=F) ... and myList %>% lapply(function(x) ifelse(length(x) == 0, NA, x)) %>% lapply(function(x) diff(x) / lag(x, -1)) but neither work.


Solution

  • One way around this is to use tryCatch to catch the error raised by the empty list element and return NA (or whatever else):

    lapply(myList, function(x) tryCatch(
      { diff(x) / lag(x, -1) }, 
      error=function(e){ NA }
      ))
    
    # [[1]]
    # 2003-02-03 2003-02-07 2003-02-09 2003-02-14 
    #         NA  -1.431227   2.245691   0.100597 
    # 
    # [[2]]
    # 2003-02-03 2003-02-07 2003-02-09 2003-02-14 
    # -0.9078077 12.8523189 -1.2523403         NA 
    # 
    # [[3]]
    # [1] NA
    # 
    # [[4]]
    # 2003-02-03 2003-02-07 2003-02-09 2003-02-14 
    #  -1.177138         NA         NA  -2.203719