在R中扩大窗口滚动回归

时间:2019-12-23 20:36:48

标签: r regression rolling-computation

我想在数据框中的两个变量之间进行滚动线性回归,并使用扩大的窗口,并按第三类别列进行分组。

例如,在下面的玩具数据框中,我想使用所有行直到感兴趣的行来提取按z分组的lm(y〜x)的系数。因此,对于第2行,用于回归的数据集将为第1行:2,对于第3行将为第1行:3,对于第4行将仅为第4行,因为它是分类变量为z = b的第一行

dframe<-data.frame(x=c(1:10),y=c(8:17), z=c("a","a","a","b","b","b","b","b","b","b"))

使用rollify功能,除了扩展窗口外,我还能得到想要的东西。下面我使用的窗口大小为2

rol <- rollify(~coef(lm(.x~0+.y)),2) 
output<-dframe %>%  group_by(z) %>% mutate(tt=rol(x,y))

具体来说,我不知道如何为rollify函数提供可变的窗口大小。有可能吗?

广泛地思考,执行此操作的有效方法是什么?我需要在几万行上做

2 个答案:

答案 0 :(得分:1)

1)rollapplyr 首先拆分dframe,然后在拆分的每个组件上运行rollapplyr。请注意,rollapplyr可以将宽度向量作为第二个参数。

library(zoo)

roll <- function(data, n = nrow(data)) {
  rollapplyr(1:n, 1:n, function(ix) coef(lm(y ~ x+0, data, subset = ix))[[1]])
}

L <- split(dframe[-3], dframe[[3]])
transform(dframe, roll = unlist(lapply(L, roll)))

给予:

    x  y z     roll
a1  1  8 a 8.000000
a2  2  9 a 5.200000
a3  3 10 a 4.000000
b1  4 11 b 2.750000
b2  5 12 b 2.536585
b3  6 13 b 2.363636
b4  7 14 b 2.222222
b5  8 15 b 2.105263
b6  9 16 b 2.007380
b7 10 17 b 1.924528

1a)。一种变体是使用ave而不是split

n <- nrow(dframe)
transform(dframe, roll = ave(1:n, z, FUN = function(ix) roll(dframe[ix, ]))

2)dplyr / rollapplyr ,除了我们使用dplyr进行分组外,这是相同的。 roll来自(1)。

library(dplyr)
library(zoo)

dframe %>%
  group_by(z) %>%
  mutate(roll = roll(data.frame(x, y))) %>%
  ungroup

给予:

# A tibble: 10 x 4
# Groups:   z [2]
       x     y z      roll
   <int> <int> <fct> <dbl>
 1     1     8 a      8   
 2     2     9 a      5.20
 3     3    10 a      4.00
 4     4    11 b      2.75
 5     5    12 b      2.54
 6     6    13 b      2.36
 7     7    14 b      2.22
 8     8    15 b      2.11
 9     9    16 b      2.01
10    10    17 b      1.92

3)基数R 也可以在没有L来自(1)的任何软件包的情况下完成此操作。结果类似于(1)。

transform(dframe, roll = unlist(lapply(L, function(data, n = nrow(data)) {
  sapply(1:n, function(i) coef(lm(y ~ x + 0, data, subset = 1:i))[[1]])
})))

3a)(1)中的roll可以在下面用roll2替换,其中不使用任何包,甚至不使用lm基础R解决方案。同样,L来自(1)。

roll2 <- function(data) with(data, cumsum(x * y) / cumsum(x * x))
transform(dframe, roll = unlist(lapply(L, roll2)))

答案 1 :(得分:0)

这是一种可以遍历您要查询的数据帧的方法:

sapply(2:nrow(dframe), function(crt.row) {
    df = dframe[1:crt.row,]
    ## compute the statistics of interest on df (e.g. run the linear model),
    ## which is the subset of the original data frame that consists of rows 1 to
    ## current
    ##
    ## for example mean of x+y
    c(crt.row=crt.row, mystat=mean(df$x + df$y))
})

        [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
crt.row    2    3    4    5    6    7    8    9   10
mystat    10   11   12   13   14   15   16   17   18