每天移动 window 具有定义起点的时间序列回归

Moving window regression on time series with defined starting point each day

我正在尝试将线性模型拟合到一个时间序列,其中回归从每天午夜开始,并使用所有数据直到第二天早上 0600(总共涵盖 30 小时)。我想在时间序列中的每一天都这样做,这也需要通过分组因素来应用。我最终需要的是在回归开始的那一天添加到数据框中的回归系数。我熟悉滚动和 window 回归以及如何使用 dplyr 跨组应用函数。我苦苦挣扎的地方是如何编写回归需要在每天午夜开始的代码。如果我要使用 window 函数,在第一天之后它将从午夜提前六个小时,我不确定如何将 window 移回午夜。似乎我需要在每次迭代时指定 window 大小和 lag/lead,但无法想象如何实现它。任何见解表示赞赏。

这里是一些示例数据。我想做模特 dv ~ datetime, by = grp

df <- dplyr::arrange(data.frame(datetime = seq(as.POSIXct("2020-09-19 00:00:00"), as.POSIXct("2020-09-30 00:00:00"),"hour"), 
grp = rep(c('a', 'b', 'c'), 265), 
dv = rnorm(795)),grp, datetime)

我们假设我们希望每个回归覆盖 30 行(末尾的任何存根除外)并且我们应该为每个回归向前移动 24 小时,以便在 grp 中每个日期有一个回归。

ans <- df %>%
  group_by(grp) %>%
  group_modify(~ {
    r <- rollapplyr(1:nrow(.), 30, by = 24,
            function(ix) coef(lm(dv ~ datetime, ., subset = ix)), 
            align = "left", partial = TRUE)
    data.frame(date = head(unique(as.Date(.$datetime)), nrow(r)), 
      coef1 = r[, 1], coef2 = r[, 2])
  }) %>%
  ungroup

给予:

> ans
# A tibble: 36 x 4
   grp   date          coef1         coef2
   <chr> <date>        <dbl>         <dbl>
 1 a     2020-09-19  -7698.   0.00000481  
 2 a     2020-09-20  -2048.   0.00000128  
 3 a     2020-09-21    -82.0  0.0000000514
 4 a     2020-09-22    963.  -0.000000602 
 5 a     2020-09-23   2323.  -0.00000145  
 6 a     2020-09-24   5886.  -0.00000368  
 7 a     2020-09-25   7212.  -0.00000450  
 8 a     2020-09-26 -17448.   0.0000109   
 9 a     2020-09-27   1704.  -0.00000106  
10 a     2020-09-28  15731.  -0.00000982  
# ... with 26 more rows

重新阅读问题后,我将其替换为上面的内容。 在 group 中创建 g,它对自上次早上 6 点以来的值进行分组,并将 width 设为自最近的早上 6 点以来的行数。然后 运行 rollapplyr 使用宽度向量来定义要回归的宽度。

library(dplyr)
library(zoo)  

ans <- df %>%
  group_by(grp) %>%
  group_modify(~ {
    g <- cumsum(format(.$datetime, "%H") == "06")
    width = 1:nrow(.) - match(g, g) + 1
    r <- rollapplyr(1:nrow(.), width, 
            function(ix) coef(lm(dv ~ datetime, ., subset = ix)), 
            partial = TRUE, fill = NA)
    mutate(., coef1 = r[, 1], coef2 = r[, 2])
  }) %>%
  ungroup

给予:

> ans
# A tibble: 795 x 5
   grp   datetime                 dv       coef1      coef2
   <chr> <dttm>                <dbl>       <dbl>      <dbl>
 1 a     2020-09-19 00:00:00 -0.560       -0.560 NA        
 2 a     2020-09-19 01:00:00 -0.506   -24071.     0.0000150
 3 a     2020-09-19 02:00:00 -1.76    265870.    -0.000166 
 4 a     2020-09-19 03:00:00  0.0705  -28577.     0.0000179
 5 a     2020-09-19 04:00:00  1.95   -248499.     0.000155 
 6 a     2020-09-19 05:00:00  0.845  -205918.     0.000129 
 7 a     2020-09-19 06:00:00  0.461        0.461 NA        
 8 a     2020-09-19 07:00:00  0.359    45375.    -0.0000284
 9 a     2020-09-19 08:00:00 -1.40    412619.    -0.000258 
10 a     2020-09-19 09:00:00 -0.446   198902.    -0.000124 
# ... with 785 more rows

备注

使用的输入

set.seed(123)
df <- dplyr::arrange(data.frame(datetime = seq(as.POSIXct("2020-09-19 00:00:00"), as.POSIXct("2020-09-30 00:00:00"),"hour"), 
grp = rep(c('a', 'b', 'c'), 265), 
dv = rnorm(795)),grp, datetime)