创建跟踪每个主题完成的周期数的列

Create column that tracks number of cycles each subject completes

我正在处理一个数据集,该数据集计算受试者对某些位置(或位置类型)的访问次数。当一个主题访问某个位置时(在我的示例中,我们会说它是位置 "X"),每个主题的访问计数都会重置。

我有一个分组变量可以帮助我在 "X" 和 "non-X" 位置之间进行过滤,但我想跟踪每个主题出现的序列数。

library(dplyr)
location <- c("A", "B", "X", "A", "C", "X", "A", "X", "C", "A", "B", "B", "A", "A", "X") 
group <- c(1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0)
id <- c(111, 111, 111, 111, 112, 112, 113, 113, 113, 113, 113, 114, 114, 114, 114)

df <- data.frame(id, group, location)

df <- within(df, {
    ## this produces a lot of warnings, but it achieves my desired result
    count = ave(id, group, cumsum(group == 0), id, FUN = seq)
    }) %>%
    mutate(count = ifelse(group == 0, yes = 0, no = count)) ## mark restarts

print(df)
     id location group count
 1  111        A     1     1
 2  111        B     1     2
 3  111        X     0     0
 4  111        A     1     1
 5  112        C     1     1
 6  112        X     0     0
 7  113        A     1     1
 8  113        X     0     0
 9  113        C     1     1
10  113        A     1     2
11  113        B     1     3
12  114        B     1     1
13  114        A     1     2
14  114        A     1     3
15  114        X     0     0

感谢 Whosebug,我找到了在我的数据中的每个主题中生成序列所需的代码。但是,这只会保留每个数据事件的 运行 计数。我希望能够记录每个受试者数据中计数重置的次数,并将其保存为变量以帮助进行其他分析。

我一直在为如何正确描述我需要的东西而苦苦挣扎,并且生成这样的序列并不是我在编程方面的经验。我正在处理数十万个 ID,所以我不愿意尝试将任何这些操作塞入 R 中的 for 循环中。关于如何以更直接和 R 友好的方式完成此操作有什么建议吗?

这是我希望达到的目标的示例:

     id location group count cycle
 1  111        A     1     1     1
 2  111        B     1     2     1
 3  111        X     0     0     0
 4  111        A     1     1     2
 5  112        C     1     1     1
 6  112        X     0     0     0
 7  113        A     1     1     1
 8  113        X     0     0     0
 9  113        C     1     1     2
10  113        A     1     2     2
11  113        B     1     3     2
12  114        B     1     1     1
13  114        A     1     2     1
14  114        A     1     3     1
15  114        X     0     0     0

这个函数 returns 我正在寻找的东西,但我不确定它能否很好地扩展到实际数据:

trackCycle <- function(sequence) {
    cycle <- 1
    out <- c()
    for (i in 1:length(sequence)) {
        if(i != 1 & sequence[i] == 0) {
            cycle <- cycle + 1
            out <- c(out, 0)
        } else {
            out <- c(out, cycle)
        }
    }
    out
}

df %>%
   group_by(id) %>%
   mutate(cycle = trackCycle(count))

来自评论的直接解决方案:

df <- df %>%
    group_by(id) %>%
    mutate(cycle = 1 + cumsum(location == "X"))

df[df$location == "X", "cycle"] <- 0