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.
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