The Rolling Regression in R Using Roll Apply

How to perform rolling regression in R with this dataset?

All columns of df are the same

all(df == df[, 1])
## [1] TRUE

so it can perfectly predict X1 using X2 and the others are not needed so it gives NA.

Regarding the rollapply code it only gave coefficients because that is what you asked for coef(lm(...)) . Your function should return a vector of whatever it is you want to get out.

It does a regression for rows 1:24, rows 2:25, ... rows 196:219 so clearly there are 196 such sets so the result has 196 rows. If you specify fill=NA then it will pad it with NAs to give the same number of rows as df.

Note that rollapplyr is available which defaults to align = "right".

Here is a possible function that returns a variety of information:

library(broom)

stats <- function(x) {
fm <- lm(X1 ~., as.data.frame(x))
c(coef(fm), unlist(glance(fm)))
}
rollapplyr(df, width = 24, FUN = stats, by.column = FALSE)

Rollapply for rolling regression with different window sizes, save coefficients in matrixes

mov.reg is not an lm objct, so it does not make sense to take coefficients of it. Also there is a reference to chron in the dput output so we need to load the chron package.

Xq is not specified but rather two separate xts objects are shown so we have assumed that those two are called x and y. Then create a single zoo object z from them. Now define a Coef function which takes a matrix with x and y columns and performs the indicated regression returning the coefficients. Also define roll which takes the width as input and runs rollapplyr with the desired arguments. Now use lapply to run roll with each width producing a list of zoo objects. This list has one component for each element in widths consisting of a zoo object with intercept and slope columns. Finally extract the intercepts from each component in the list and form a zoo object and do the same for the slopes. Note that if L is a list of zoo objects then do.call("merge", L) will produce a single zoo object from it.

library(xts) # this also loads zoo
library(chron)

# inputs are xts objects x and y
z <- cbind(x = as.zoo(x)[, 1], y = as.zoo(y)[, 1])

Coef <- function(m) coef(lm(y ~ x, as.data.frame(m)))
roll <- function(w) rollapplyr(z, w, Coef, by = 24, by.column = FALSE)
widths <- seq(24, 240, 24)
names(widths) <- widths # lapply will use these names for its output

L <- lapply(widths, roll)
intercepts <- do.call("merge", lapply(L, "[", TRUE, 1)) # extract 1st columns
slopes <- do.call("merge", lapply(L, "[", TRUE, 2)) # 2nd columns

Alternately do the rollapplyr twice replacing the last 3 lines with:

intercepts <- do.call("merge", lapply(widths, function(w) roll(w)[, 1]))
slopes <- do.call("merge", lapply(widths, function(w) roll(w)[, 2]))

Rolling Regression in R

Define a function which returns the year and R squared given a subset of rows of df (without ID) and then use rollapply with it.

library(dplyr)
library(zoo)

R2 <- function(x) {
x <- as.data.frame(x)
c(YEAR = tail(x$YEAR, 1), R2 = summary(lm(DV ~ IV, x))$r.squared)
}

df %>%
group_by(ID) %>%
do(data.frame(rollapply(.[-1], 20, by = 4, R2, by.column = FALSE))) %>%
ungroup

giving:

# A tibble: 12 x 3
ID YEAR R2
<fct> <dbl> <dbl>
1 1 2005 0.0133
2 1 2006 0.130
3 1 2007 0.0476
4 1 2008 0.0116
5 1 2009 0.00337
6 1 2010 0.00570
7 2 2005 0.0481
8 2 2006 0.00527
9 2 2007 0.0158
10 2 2008 0.0303
11 2 2009 0.235
12 2 2010 0.116

rolling regression by group in the tidyverse?

Define a function Coef whose argument is formed from cbind(y, x) and which regresses y on x with an intercept, returning the coefficients. Then apply rollapplyr using the current and prior rows over each group. If by last you meant the 2 prior rows to the current row, i.e. exclude the current row, then replace 2 with list(-seq(2)) as an argument to rollapplyr.

Coef <- . %>% as.data.frame %>% lm %>% coef

mydata %>%
group_by(group) %>%
do(cbind(reg_col = select(., y, x) %>% rollapplyr(2, Coef, by.column = FALSE, fill = NA),
date_col = select(., date))) %>%
ungroup

giving:

# A tibble: 8 x 4
group `reg_col.(Intercept)` reg_col.x date
<chr> <dbl> <dbl> <date>
1 a NA NA 2016-06-01
2 a 0 0.500 2016-06-02
3 a 0 0.500 2016-06-03
4 a 0 0.500 2016-06-04
5 b NA NA 2016-06-03
6 b 0.00000000000000126 0.333 2016-06-04
7 b - 0.00000000000000251 0.333 2016-06-05
8 b 0 0.333 2016-06-06

Variation

A variation of the above would be:

mydata %>% 
group_by(group) %>%
do(select(., date, y, x) %>%
read.zoo %>%
rollapplyr(2, Coef, by.column = FALSE, fill = NA) %>%
fortify.zoo(names = "date")
) %>%
ungroup

Slope Only

If only the slope is needed there are further simplifications possible. We use the fact that the slope equals cov(x, y) / var(x).

slope <- . %>% { cov(.[, 2], .[, 1]) / var(.[, 2])}
mydata %>%
group_by(group) %>%
mutate(slope = rollapplyr(cbind(y, x), 2, slope, by.column = FALSE, fill = NA)) %>%
ungroup

Applying a rolling window regression to an XTS series in R

There are several problems here:

  • rollapply passes a matrix but lm requires a data.frame.
  • rollapply applies the function to each column separately unless we
    specify by.column=FALSE.
  • you may or may not want the result to be
    right aligned with the dates but if you do use rollapplyr :

1) Incorporating the above we have:

dolm <- function(x) coef(lm(USDZAR ~ ., data = as.data.frame(x))))
rollapplyr(fxr, 62, dolm, by.column = FALSE)

2) An alternative to the lm in the dolm above is to use lm.fit which directly works with matrices and is also faster:

dolm <- function(x) coef(lm.fit(cbind(Intercept = 1, x[,-1]), x[,1]))


Related Topics



Leave a reply



Submit