R中事件之间的累积总和

zhte4eai  于 2023-05-11  发布在  其他
关注(0)|答案(1)|浏览(158)

我知道累积求和在R中相当容易,但我被这个特定的用例卡住了。
在下面的表中,我希望第4列是任何个人的连续接受之间的累积总和,在他们接受的每个示例中重置计数器。
因此,例如,用户1的数据将行1为0,这是他们接受的任何一个的第一个示例,所有用户在他们的第一个接受时都应该有0。第2行将有1(连续邀请之间的一天),第3行将有21(从他们的最后一个20+从初始的1),但他们在第5行的条目将有53,因为计数器在他们的最后一次接受时被重置。它不应该在随后的接受中显示零,应该暗示零。唯一的零应该是他们的第一个。

user  status_name invitationDate
  <fct> <fct>       <date>        
1 1     Accepted    2021-09-09    
2 1     Declined    2021-09-10    
3 1     Accepted    2021-09-30    
4 4     Accepted    2021-11-10    
5 1     Accepted    2021-11-22    
6 4     Declined    2021-11-29

我已经包含了重新创建下表的代码。

df <- tribble(
  ~user, ~status_name, ~invitationDate,
  "1", "Declined", "2021-07-13",
  "4", "Declined", "2021-07-31",
  "1", "Accepted", "2021-09-09",
  "1", "Declined", "2021-09-10",
  "1", "Accepted", "2021-09-30",
  "4", "Accepted", "2021-11-10",
  "3", "Declined", "2021-11-12",
  "2", "Declined", "2021-11-18",
  "1", "Accepted", "2021-11-22",
  "4", "Declined", "2021-11-29"
) %>%
  mutate(
    user = as.factor(user),
    status_name = as.factor(status_name),
    invitationDate = as.Date(invitationDate, format = "%Y-%m-%d")
  ) %>%
  group_by(user) %>%
  mutate(cumsum = cumsum(status_name == "Accepted")) %>%
  filter(cumsum > 0) %>%
  select(-cumsum)
j2cgzkjk

j2cgzkjk1#

请注意,输入已经按user分组,因此使用cumsum将第一个Accepted和随后的Declined行标记为cs=1,将随后的Accepted和随后的Declined行标记为cs=2,依此类推。然后将每个cs匹配到遇到的第一行,该行的cs值为1减去当前cs值,得到ix,并从当前行的日期中减去ix行的日期。如果您希望将df保留为分组,请省略ungroup行。

df %>%
  mutate(cs = cumsum(status_name == "Accepted"),
    ix = match(cs - 1, cs, nomatch = 1),
    dif = as.numeric(invitationDate - invitationDate[ix])) %>%
  ungroup %>%
  select(-cs, -ix)

给予

# A tibble: 6 × 4
  user  status_name invitationDate   dif
  <fct> <fct>       <date>         <dbl>
1 1     Accepted    2021-09-09         0
2 1     Declined    2021-09-10         1
3 1     Accepted    2021-09-30        21
4 4     Accepted    2021-11-10         0
5 1     Accepted    2021-11-22        53
6 4     Declined    2021-11-29        19

上面的一个变体是将csix计算组合到priorTRUE函数中,该函数接受逻辑向量,并为每个组件返回先前TRUE值的索引。这避免了引入临时列csix以及相应的select。类似地,如果希望保留分组,则省略ungroup行。

priorTRUE <- function(x) {
  cs <- cumsum(x)
  match(cs - 1, cs, nomatch = 1)
}

df %>%
  mutate(dif = as.numeric(
    invitationDate - invitationDate[priorTRUE(status_name == "Accepted")])) %>%
  ungroup

相关问题