The task is to dynamically merge multiple xts
objects into one big blob with suffixes, where suffixes are essentially the column names for the xts objects.
Sample Data:
library(xts)
a <- data.frame(alpha=1:10, beta=2:11)
xts1 <- xts(x=a, order.by=Sys.Date() - 1:10)
b <- data.frame(alpha=3:12, beta=4:13)
xts2 <- xts(x=b, order.by=Sys.Date() - 1:10)
c <- data.frame(alpha=5:14, beta=6:15)
xts3 <- xts(x=c, order.by=Sys.Date() - 1:10)
Static way of merging:
$> merge.zoo(xts1, xts2, xts3, suffixes=c("A", "B", "C"))
# output
alpha.A beta.A alpha.B beta.B alpha.C beta.C
2022-03-11 10 11 12 13 14 15
2022-03-12 9 10 11 12 13 14
2022-03-13 8 9 10 11 12 13
2022-03-14 7 8 9 10 11 12
2022-03-15 6 7 8 9 10 11
2022-03-16 5 6 7 8 9 10
2022-03-17 4 5 6 7 8 9
2022-03-18 3 4 5 6 7 8
2022-03-19 2 3 4 5 6 7
2022-03-20 1 2 3 4 5 6
I might have more than 3 xts objets and 3 is just an arbitrary demonstration.
I've tried do.call
but my do.call
attempt failed with/out suffixes because I can't wrap up the 3 xts objects into a data structure that's accepted by do.call as a list (in R's language it should be a vector of 3 items).
do.call
Demo:
# do.call with xts objects as separate args and suffixes, works
do.call(merge.zoo, list(xts1, xts2, xts3, suffixes=c("A", "B", "C")))
# do.call with xts objects wrapped up as list and suffixes, failed
# because R takes each element of list as vector and essentially a list of xts objects is a list of 3 lists, each of which has a xts object.
xts.list <- list(xts1, xts2, xts3)
# check data type
class(xts.list[[1]]) # output: xts,zoo
class(xts.list[1]) # output: list
# do.call failed attempt
do.call(merge.zoo, list(xts.list, suffixes=c("A", "B", "C")))
# Error Message
Error in zoo(structure(x, dim = dim(x)), index(x), ...) :
“x” : attempt to define invalid zoo object
In other words, if I can unpack the list into dynamic number of arguments, I'd be able to get this idea to work; however I can't seem to find a way to either unpack arguments in R or some other solutions.
Disclaimer: The ultimate problem I am trying to solve is to be able to plot the time series data in the multi-panel view eventually; ggplot
does not work with most of the packages I am using on a daily basis.
Disclaimer 2: merge.xts
ignores suffixes (a bug), merge.zoo
is the working alternative. For more information take a look here
CodePudding user response:
We can pass everything in a list
i.e.
library(zoo)
c(xts.list, list(suffixes=c("A", "B", "C")))
Now, use the merge
in do.call
do.call(merge.zoo, c(xts.list, list(suffixes=c("A", "B", "C"))))
-output
alpha.A beta.A alpha.B beta.B alpha.C beta.C
2022-03-11 10 11 12 13 14 15
2022-03-12 9 10 11 12 13 14
2022-03-13 8 9 10 11 12 13
2022-03-14 7 8 9 10 11 12
2022-03-15 6 7 8 9 10 11
2022-03-16 5 6 7 8 9 10
2022-03-17 4 5 6 7 8 9
2022-03-18 3 4 5 6 7 8
2022-03-19 2 3 4 5 6 7
2022-03-20 1 2 3 4 5 6
Note that the first argument to merge
is variadic component (...
- which can take one or more xts data, where as all the other components are named and that is the reason we are creating the list
with names
only for those components i.e. suffixes. According to ?merge
merge(..., all = TRUE, fill = NA, suffixes = NULL, join = "outer", retside = TRUE, retclass = "xts", tzone = NULL, drop=NULL, check.names=NULL)
Thus, when we want to append a list
i.e. xts.list
with another list element, wrap the second named vector in a list
and then just c
oncatenate. It is similar to
> c(list(1), list(a = 1, b = 2))
[[1]]
[1] 1
$a
[1] 1
$b
[1] 2
and not the following as this create a nested list
> list(list(1), list(a = 1, b = 2))
[[1]]
[[1]][[1]]
[1] 1
[[2]]
[[2]]$a
[1] 1
[[2]]$b
[1] 2