在 R 中扩展 window 的滚动回归
Rolling regression with expanding window in R
我想在数据框中的两个变量之间进行滚动线性回归,扩展 window,按第三个分类列分组。
例如,在下面的玩具数据框中,我想使用所有行提取按 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 函数,除了扩展 window,我可以得到我想要的东西。下面我使用了 window 大小为 2
rol <- rollify(~coef(lm(.x~0+.y)),2)
output<-dframe %>% group_by(z) %>% mutate(tt=rol(x,y))
具体来说,我不知道如何向 rollify 函数提供变量 window 大小。可能吗?
从广义上思考,执行此操作的有效方法是什么?我需要在几 10000 行上执行此操作
这是一种可以滚动遍历您所询问的数据框的方法:
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
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, ]))
1b) 在最初回答问题一段时间后添加了这个备选方案。
reg <- function(x) coef(lm(x[, 2] ~ x[, 1] + 0))
n <- nrow(dframe)
w <- ave(1:n, dframe$z, FUN = seq_along)
transform(dframe,
roll = rollapplyr(zoo(cbind(x, y)), w, reg, by.column = FALSE, coredata = FALSE))
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) Base 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) roll
in (1) 可以替换为下面的 roll2
其中不使用包甚至不使用 lm
给我们另一个基本的 R 解决方案。同样,L
来自 (1).
roll2 <- function(data) with(data, cumsum(x * y) / cumsum(x * x))
transform(dframe, roll = unlist(lapply(L, roll2)))
我想在数据框中的两个变量之间进行滚动线性回归,扩展 window,按第三个分类列分组。
例如,在下面的玩具数据框中,我想使用所有行提取按 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 函数,除了扩展 window,我可以得到我想要的东西。下面我使用了 window 大小为 2
rol <- rollify(~coef(lm(.x~0+.y)),2)
output<-dframe %>% group_by(z) %>% mutate(tt=rol(x,y))
具体来说,我不知道如何向 rollify 函数提供变量 window 大小。可能吗?
从广义上思考,执行此操作的有效方法是什么?我需要在几 10000 行上执行此操作
这是一种可以滚动遍历您所询问的数据框的方法:
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
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, ]))
1b) 在最初回答问题一段时间后添加了这个备选方案。
reg <- function(x) coef(lm(x[, 2] ~ x[, 1] + 0))
n <- nrow(dframe)
w <- ave(1:n, dframe$z, FUN = seq_along)
transform(dframe,
roll = rollapplyr(zoo(cbind(x, y)), w, reg, by.column = FALSE, coredata = FALSE))
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) Base 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) roll
in (1) 可以替换为下面的 roll2
其中不使用包甚至不使用 lm
给我们另一个基本的 R 解决方案。同样,L
来自 (1).
roll2 <- function(data) with(data, cumsum(x * y) / cumsum(x * x))
transform(dframe, roll = unlist(lapply(L, roll2)))