我知道累积求和在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)
1条答案
按热度按时间j2cgzkjk1#
请注意,输入已经按
user
分组,因此使用cumsum
将第一个Accepted
和随后的Declined
行标记为cs=1
,将随后的Accepted
和随后的Declined
行标记为cs=2
,依此类推。然后将每个cs
匹配到遇到的第一行,该行的cs
值为1减去当前cs
值,得到ix
,并从当前行的日期中减去ix
行的日期。如果您希望将df
保留为分组,请省略ungroup
行。给予
上面的一个变体是将
cs
和ix
计算组合到priorTRUE
函数中,该函数接受逻辑向量,并为每个组件返回先前TRUE值的索引。这避免了引入临时列cs
和ix
以及相应的select
。类似地,如果希望保留分组,则省略ungroup
行。