Question

I have a list containing time series data stored in xts format. The lists are of unequal lengths, and only a subset of the dates / rows intersect.

I wish to iterate over combinations of the lists with various functions -- for the case in point, let's just say i wish to find differences.

I am able to do this for each single combination, but am unable to get a higher order function working to iterate across the batch.

So, for example, each of the following work:

combn(c(1,2), 2, function(X) exData[[X[1]]] - exData[[X[2]]])
combn(c(1,3), 2, function(X) exData[[X[1]]] - exData[[X[2]]])
combn(c(2,3), 2, function(X) exData[[X[1]]] - exData[[X[2]]])

However, my attempt at a higher-order function fails:

combn(1:length(exData), 2, function(X) exData[[X[1]]] - exData[[X[2]]])

Instead it returns the error: Error in combn(1:length(exData), 2, function(X) exData[[X[1]]] - exData[[X[2]]]) : number of items to replace is not a multiple of replacement length.

I am not sure what this means ...

An example data set may be constructed as follows:

set.seed(1)
dtime <- seq(Sys.Date(), length.out = 20, by='day')
exData <- replicate(4, runif(sample(9:12, 1)), simplify=FALSE)
exData <- lapply(exData, 
                 function(x) xts(x, 
                                 order.by = sort(sample(dtime, 
                                                        length(x)))[1:length(x)]))

The salient point is that not all dates are in each xts object that's contained in the list, and that the lists are of unequal length. At this point, i'm using the xts object rules to control the application of the function -- though that might change later.

So what's the appropriate way of looping over each of the combinations? The combinations are given by each of the columns in the below:

combos <- combn(1:4, 2)
R> combos
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    1    1    2    2    3
[2,]    2    3    4    3    4    4

Note: in the real life case, each xts has multiple columns, and allowing for variety in the function that is applied to the two inputs is required. With the help of @flodel, i made the following functions, which preserve the column names after the operation, and have the desired flexibility.

funDiffName <- function(XTS, loc, ff){
# takes a list of XTS objects, a location pair (from combn), and the function to apply
# preserves names following the application of ff
    ffxy <- ff(XTS[[loc[1]]], XTS[[loc[2]]])
    names(ffxy) <- paste0(names(XTS[[1]]), "x", names(XTS[[2]]))
    ffxy
}

SecPx_diff <- combn(1:(length(SecPx_l)), 2,
                    function(X) funDiffName(SecPx_l, X, `-`),
                    simplify = FALSE)
Was it helpful?

Solution

The error comes from the fact that R is trying to put the results into an array, but the pieces have different sizes... The solution is to request a list by adding simplify = FALSE to the combn call.

OTHER TIPS

You need to cbind them first. for xts, cbind function binds the two xts by their index.

combn(1:length(exData), 2, function(X) {
        temp <- cbind(exData[[X[1]]], exData[[X[2]]])
        temp <- (temp[, 1] - temp[, 2])
        temp[!is.na(temp)]
    }, simplify = FALSE)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top