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 (...). Uselibrary
in your example. This will make it easier to debug the existence of missing packages since in that case it will stop at thelibrary
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 unlessby.column = FALSE
is used.using
test
withingroup_by
will not causetest
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)
}
Exampledata("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
Replace Accented Characters in R with Non-Accented Counterpart (Utf-8 Encoding)
How to Fill Nas with Locf by Factors in Data Frame, Split by Country
Functions Available for Tufte Boxplots in R
Why Does Rendering a PDF from Rmarkdown Require Closing Rstudio Between Renders
R Fails After Installing Gtk and Rgtk2
How to Clean Twitter Data in R
Histogram with "Negative" Logarithmic Scale in R
Multiple Strings with Str_Detect R
Is There a Technical Difference Between "=" and "<-"
Install R Packages from Github Downloading Master.Zip
R: Using Rgl to Generate 3D Rotatable Plots That Can Be Viewed in a Web Browser
Ggplot2: Geom_Text() with Facet_Grid()
Adding Text to Ggplot Geom_Jitter Points That Match a Condition