我正在尝试根据以下玩具数据计算滚动总和:
structure(list(Tag = c("1", "1", "1", "1", "2", "2", "2", "2", "2",
"2"), ID = c("A", "A", "A", "B", "J", "J", "J", "A", "A", "A" ),
correctvis = c(1, 0, 1, 1, 1, 0, 1, 0, 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", "tbl", "data.frame"))
我已经同时使用data.table
和dplyr
了:
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个,导致出现错误:
在大于窗口的范围内无法滚动应用 数据长度
我的问题
或
有没有一种方法可以使rollify代码适合我的窗口大小。我曾经想到的一个想法是使用case_when:
rolling_sum <- rollify(.f = sum, window = case_when(n=1~1,n=2~2, etc.))
但是我无法使它正常工作。
答案 0 :(得分:2)
以下是使用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