组边界内的滚动总和

问题描述

我正在尝试根据以下玩具数据计算滚动总和:

structure(list(Tag = c("1","1","2","2"),ID = c("A","A","B","J","A" ),correctvis = c(1,1,0)),row.names = c(NA,-10L),groups = structure(list(ID = "A",Tag = "1",.rows = structure(list(1:10),ptype = integer(0),class = c("vctrs_list_of","vctrs_vctr","list"))),row.names = 1L,class = c("tbl_df","tbl","data.frame"),.drop = TRUE),class = c("grouped_df","tbl_df","data.frame"))

我已经同时使用data.tabledplyr了:

test <- as.data.table(df)[,sums2 := frollsum(correctvis,7),by = c("ID","Tag")]

test <- df %>%
  group_by(ID,Tag) %>%
  mutate(sums = roll_sum(correctvis,7,align = "right",fill = NA)) 

两个结果都相同。

注意:实际上,我的标签/ ID列表持续的时间更长,这就是为什么我使用7而不是较小的窗口的原因。

问题: 尽管使用了group_by和by =,roll_sum和froll_sum使用的窗口仍超出了组的边界。也就是说:我想开始计数,好像每个分组之前的所有值correctvis都是0(对于该分组)。 以下代码似乎确实尊重分组(基于tibbletime包):

rolling_sum <-  rollify(.f = sum,window = 7)
df <- df %>%
 group_by(ID,Tag) %>%
 mutate(sums2 = rolling_sum(correctvis))

但是,此代码无法正常工作,因为在某些情况下,每个特定分组的观察值少于7个,导致出现错误

在大于窗口的范围内无法滚动应用 数据长度

我的问题

  • 我是否可以调整dplyr / data.table代码,使其在应用滚动总和时尊重我的分组?

  • 有没有一种方法可以使rollify代码适合我的窗口大小。我曾经想到的一个想法是使用case_when:

    rolling_sum <- rollify(.f = sum,window = case_when(n=1~1,n=2~2,etc.))

但是我无法使它正常工作。

解决方法

以下是使用data.table::frollmean的选项:

library(data.table)
k <- 7L
setDT(df)[,if (.N > k) frollmean(correctvis,c(1L:k,rep(k,.N - k)),adaptive=TRUE) 
        else frollmean(correctvis,seq_len(.N),adaptive=TRUE),.(ID,Tag,rleid(ID,Tag))]

输出:

    ID Tag rleid        V1
 1:  A   1     1 1.0000000
 2:  A   1     1 0.5000000
 3:  A   1     1 0.6666667
 4:  B   1     2 1.0000000
 5:  J   2     3 1.0000000
 6:  J   2     3 0.5000000
 7:  J   2     3 0.6666667
 8:  A   2     4 0.0000000
 9:  A   2     4 0.5000000
10:  A   2     4 0.3333333