具有依赖于其在上一行中的值的变异的变量定义

Variable definition with mutate that depends on its value in the previous row

我有以下格式的一些数据:

   time click       interaction
1   407 FALSE              TRUE
2   408  TRUE              TRUE
3   409 FALSE             FALSE
4   410 FALSE             FALSE
5   411 FALSE             FALSE
6   412 FALSE             FALSE
7   413 FALSE             FALSE
8   414 FALSE             FALSE
9   415 FALSE             FALSE
10  416 FALSE             FALSE
11  417 FALSE             FALSE
12  418 FALSE             FALSE
13  419 FALSE             FALSE
14  420 FALSE             FALSE
15  421 FALSE             FALSE
16  422 FALSE             FALSE
17  423 FALSE             FALSE
18  424 FALSE             FALSE
19  425 FALSE             FALSE
20  426 FALSE             FALSE
21  427 FALSE             FALSE
22  428 FALSE             FALSE
23  429 FALSE             FALSE
24  430 FALSE             FALSE
25  431 FALSE             FALSE
26  432 FALSE             FALSE
27  433 FALSE             FALSE
28  434 FALSE             FALSE
29  435 FALSE              TRUE
30  436 FALSE             FALSE

它表示用户每秒如何与应用程序交互(点击和其他交互事件,如打字、滚动等,interaction 在有任何交互、点击或其他情况时为真)。我想计算一个新变量,该变量在单击 后没有交互 直到他们再次开始交互的范围内为真。

所以对于这个新变量,我希望它为真,如果有:

  • 前一秒点击,当前秒无交互(点击或其他),或者
  • 上一秒点击无交互,当前秒无交互

我用 dplyr 尝试过这样的事情:

activity %>% mutate(
    nothing.after.click = (lag(click) == TRUE & interaction == FALSE) |
        (lag(nothing.after.click) == TRUE & interaction == FALSE)
)

但不幸的是它不起作用(它说 "Error: object 'nothing.after.click' not found")。我怎样才能做到这一点?如果 dplyr 无法实现,我欢迎使用其他东西。

这是我想要的输出:

   time click       interaction nothing.after.click
1   407 FALSE              TRUE               FALSE
2   408  TRUE              TRUE               FALSE
3   409 FALSE             FALSE                TRUE
4   410 FALSE             FALSE                TRUE
5   411 FALSE             FALSE                TRUE
6   412 FALSE             FALSE                TRUE
7   413 FALSE             FALSE                TRUE
8   414 FALSE             FALSE                TRUE
9   415 FALSE             FALSE                TRUE
10  416 FALSE             FALSE                TRUE
11  417 FALSE             FALSE                TRUE
12  418 FALSE             FALSE                TRUE
13  419 FALSE             FALSE                TRUE
14  420 FALSE             FALSE                TRUE
15  421 FALSE             FALSE                TRUE
16  422 FALSE             FALSE                TRUE
17  423 FALSE             FALSE                TRUE
18  424 FALSE             FALSE                TRUE
19  425 FALSE             FALSE                TRUE
20  426 FALSE             FALSE                TRUE
21  427 FALSE             FALSE                TRUE
22  428 FALSE             FALSE                TRUE
23  429 FALSE             FALSE                TRUE
24  430 FALSE             FALSE                TRUE
25  431 FALSE             FALSE                TRUE
26  432 FALSE             FALSE                TRUE
27  433 FALSE             FALSE                TRUE
28  434 FALSE             FALSE                TRUE
29  435 FALSE              TRUE               FALSE
30  436 FALSE             FALSE               FALSE

最终,我们的目标是过滤掉 nothing.after.click 为真的这些行,所以如果有另一种方式来考虑这个问题,我也欢迎。

您不能在初始定义中引用变量。我们能做的就是分多次进行。

当我看你的条件时:

nothing.after.click = (lag(click) == TRUE & interaction == FALSE) |
        (lag(nothing.after.click) == TRUE & interaction == FALSE)

我在两种可能性中都看到 interaction == FALSE。所以,如果 interactionTRUE,那么 nothing.after.click(从这里开始 nac)肯定是 FALSE。否则,我还不确定,所以我将其设置为 NA。这是我的第一遍:

dat %>% mutate(nac = ifelse(interaction, FALSE, NA))

我们已经处理了 interaction == FALSE 部分,下一遍将是您的 or 子句的 lag(click) == TRUE 部分。对于 NA 的任何内容,因此尚未确定,如果 lag(click) 为 TRUE,则它将为 TRUE,否则我们将保持不变。 (== TRUE 是多余的,所以我省略了它。)

dat %>% mutate(nac = ifelse(interaction, FALSE, NA),
               nac = ifelse(lag(click) & is.na(nac), TRUE, nac))

最后一遍是 lag(nac) 部分,任何仍未定义的都设置为先前定义的值。这是 zoo:na.locf 的工作(locf 代表 "last observation carried forward"):

library(zoo)
dat %>% mutate(nac = ifelse(interaction, FALSE, NA),
               nac = ifelse(lag(click) & is.na(nac), TRUE, nac),
               nac = na.locf(nac))

#    time click interaction   nac
# 1   407 FALSE        TRUE FALSE
# 2   408  TRUE        TRUE FALSE
# 3   409 FALSE       FALSE  TRUE
# 4   410 FALSE       FALSE  TRUE
# 5   411 FALSE       FALSE  TRUE
# 6   412 FALSE       FALSE  TRUE
# 7   413 FALSE       FALSE  TRUE
# 8   414 FALSE       FALSE  TRUE
# 9   415 FALSE       FALSE  TRUE
# 10  416 FALSE       FALSE  TRUE
# 11  417 FALSE       FALSE  TRUE
# 12  418 FALSE       FALSE  TRUE
# 13  419 FALSE       FALSE  TRUE
# 14  420 FALSE       FALSE  TRUE
# 15  421 FALSE       FALSE  TRUE
# 16  422 FALSE       FALSE  TRUE
# 17  423 FALSE       FALSE  TRUE
# 18  424 FALSE       FALSE  TRUE
# 19  425 FALSE       FALSE  TRUE
# 20  426 FALSE       FALSE  TRUE
# 21  427 FALSE       FALSE  TRUE
# 22  428 FALSE       FALSE  TRUE
# 23  429 FALSE       FALSE  TRUE
# 24  430 FALSE       FALSE  TRUE
# 25  431 FALSE       FALSE  TRUE
# 26  432 FALSE       FALSE  TRUE
# 27  433 FALSE       FALSE  TRUE
# 28  434 FALSE       FALSE  TRUE
# 29  435 FALSE        TRUE FALSE
# 30  436 FALSE       FALSE FALSE

已经有一个很好的答案(+1),但这里有一个使用 base R 的替代方案。

dat$nac <- with(dat, unlist(
    sapply(split(interaction, cumsum(interaction & click)), function(x) c(F, !cumsum(x[-1])))
))

#    time click interaction   nac
# 1   407 FALSE        TRUE FALSE
# 2   408  TRUE        TRUE FALSE
# 3   409 FALSE       FALSE  TRUE
# 4   410 FALSE       FALSE  TRUE
# 5   411 FALSE       FALSE  TRUE
# 6   412 FALSE       FALSE  TRUE
# 7   413 FALSE       FALSE  TRUE
# 8   414 FALSE       FALSE  TRUE
# 9   415 FALSE       FALSE  TRUE
# 10  416 FALSE       FALSE  TRUE
# 11  417 FALSE       FALSE  TRUE
# 12  418 FALSE       FALSE  TRUE
# 13  419 FALSE       FALSE  TRUE
# 14  420 FALSE       FALSE  TRUE
# 15  421 FALSE       FALSE  TRUE
# 16  422 FALSE       FALSE  TRUE
# 17  423 FALSE       FALSE  TRUE
# 18  424 FALSE       FALSE  TRUE
# 19  425 FALSE       FALSE  TRUE
# 20  426 FALSE       FALSE  TRUE
# 21  427 FALSE       FALSE  TRUE
# 22  428 FALSE       FALSE  TRUE
# 23  429 FALSE       FALSE  TRUE
# 24  430 FALSE       FALSE  TRUE
# 25  431 FALSE       FALSE  TRUE
# 26  432 FALSE       FALSE  TRUE
# 27  433 FALSE       FALSE  TRUE
# 28  434 FALSE       FALSE  TRUE
# 29  435 FALSE        TRUE FALSE
# 30  436 FALSE       FALSE FALSE

这里的技巧是利用点击和互动同时发生的事实。然后 split 这些事件的数据并使用 cumsum 查找点击之间交互的变化。