Calculate Rolling Correlation Using Rollapply

How to calculate rolling correlations between several columns and one column in rollapply?

Use rollapplyr with the indicated function and by.column = FALSE.

# test data
stock_returns <- xts(anscombe[6:8], as.Date("2000-01-01") + seq(0, length=nrow(anscombe)))
market <- xts(anscombe[, 5], time(stock_returns))

x <- cbind(market, stock_returns)
rollapplyr(x, 5, function(x) cor(x[, 1], x[, -1]), by.column = FALSE)

giving:

2000-01-01         NA          NA         NA
2000-01-02 NA NA NA
2000-01-03 NA NA NA
2000-01-04 NA NA NA
2000-01-05 0.6912899 -0.19831742 0.8437913
2000-01-06 -0.0904641 -0.08067339 0.3773026
2000-01-07 0.3714166 -0.05974574 0.3604551
2000-01-08 0.9013902 0.90672036 -0.6537459
2000-01-09 0.9059692 0.91388127 -0.7673776
2000-01-10 0.7996265 0.89299770 -0.7032847
2000-01-11 0.7812519 0.89427224 -0.6959074

zoo::rollapply does not give the entire run of rolling correlation

The function should return a vector, not a matrix. Use the following (or omit the fill argument if you don't want the result to be filled with leading NAs):

ccor <- function(x) c(cor(x, method = "spearman"))
rollapplyr(test, 50, ccor, by.column = FALSE, fill = NA)

Also

  • require should only be used within an if (...). Use library in your example. This will make it easier to debug the existence of missing packages since in that case it will stop at the library statement rather than later on when it is harder to determine the cause.

  • the right pointing assignment arrows should be left pointing

  • in the development version of zoo a matrix or data frame (but not a plain list) output from the function specified in FUN= will be unraveled into a vector so this will produce one row for each input row:

    # install.packages("zoo", repos="http://R-Forge.R-project.org")
    rollapplyr(test, 50, cor, method = "spearman", by.column = FALSE, fill = NA)

R - Rolling correlation of each column with each other column

This provides the correlation matrix unravelled into a row for each date. There will be n*n columns where ts has n columns:

r1 <- rollapplyr(ts, 63, cor, fill = NA, by.column = FALSE)

or this will show only the lower triangle and will have choose(n, 2) columns:

ccor <- function(x) { cc <- cor(x); cc[lower.tri(cc)] }
r2 <- rollapplyr(X, 63, ccor, fill = NA, by.column = FALSE)

This can be used to assign column names, if needed.

paste_ <- function(...) paste(..., sep = "_")
names_mat <- do.call("outer", list(names(ts), names(ts), paste_))
names(r1) <- names_mat
names(r2) <- names_mat[lower.tri(names_mat)]

Rolling correlation with data.table

Try this:

corr <- function(y) cor(y[, 1], y[, 2])
dt[,rcor:=rollapplyr(.SD, 5, corr, by.column = FALSE, fill = NA)]

Rolling correlation two data frames

Invoke rollapplyr over the indexes like this:

library(zoo)

set.seed(123)

ret1 <- rnorm(10)
ret2 <- rnorm(10)

rollapplyr(seq_along(ret1), 5, function(ix) cor(ret1[ix], ret2[ix]), fill = NA)
## [1] NA NA NA NA -0.2440453 0.6974227
## [7] 0.7729576 0.9777006 0.8008661 0.8428961

or cbind the return vectors together and use by.column = FALSE :

ret <- cbind(ret1, ret2)
rollapplyr(ret, 5, function(x) cor(x[, 1], x[, 2]), by.column = FALSE, fill = NA)
## [1] NA NA NA NA -0.2440453 0.6974227
## [7] 0.7729576 0.9777006 0.8008661 0.8428961

Normally time is ascending. If you create a ts, zoo or xts time series object that is the convention used.

Rolling correlation with 'grouped by' - Error: incorrect number of dimensions

There are several problems:

  • rollapply applies to each column separately unless by.column = FALSE is used.

  • using test within group_by will not cause test to be subsetted. It will refer to the entire dataset. Use individual column names instead.

  • the column names in the code in the question must have quotes around them; otherwise, it is saying there are variables of those names containing the column names.

  • when posting to SO you need to reduce your problem to a complete reproducible example and post that. I have done it this time for you in the Note at the end.

With reference to the Note, use this code:

library(dplyr)
library(zoo)

mycor <- function(x) cor(x[, 1], x[, 2])
DF %>%
group_by(stock) %>%
mutate(Cor = rollapplyr(cbind(a, b), 4, mycor, by.column = FALSE, fill = NA)) %>%
ungroup

or this code which only uses zoo. mycor is from above.

library(zoo)

n <- nrow(DF)
roll <- function(i) rollapplyr(DF[i, c("a", "b")], 4, mycor, by.column = FALSE, fill = NA)
transform(DF, Cor = ave(1:n, stock, FUN = roll))

Note

The input in reproducible form is:

DF <- data.frame(stock = rep(LETTERS[1:2], each = 6), a = 1:6, b = (1:6)^3)

Multiple rolling correlation

rolling_correlation <- function(df, vector.1, vector.2, window.length = 15){

require(rlang)
require(tidyquant)
require(tibbletime)

#build the correlation formula
cor_roll <- rollify(~cor(.x, .y), window = window.length)

x <- map2(vector.1, vector.2, ~mutate(df,
running_cor = cor_roll(!!quo(!! sym(.x)),
!!quo(!! sym(.y))))) %>%
stats::setNames(., paste(vector.1, vector.2, sep = "_")) %>% # name the dfs in the list
bind_rows(.id = "groups") %>% spread(groups, running_cor) # add the list name as a column in the DF and then spread it

return(x)

}
Example

data("FB")
corr_df <- rolling_correlation(FB, c("open", "high", "low"), c("close", "low", "open"), 5)

help for unquoting !!quo(!! sym(.x)) was from here - look at lionel- commented on May 4, 2017
https://github.com/r-lib/rlang/issues/116



Related Topics



Leave a reply



Submit