R(dplyr)中复位的条件运行计数(累计和)

问题描述 投票:1回答:2

我正在尝试计算一个以其他变量为条件的运行计数(即累积和),它可以重置另一个变量的特定值。我在R工作,如果可能的话,我更喜欢基于dplyr的解决方案。

我想根据以下算法为运行计数cumulative创建一个变量:

  • 计算cumulativeid组合中的运行计数(age
  • 每个后续的cumulative将运行次数(trial)增加1,其中accuracy = 0block = 2condition = 1
  • cumulativetrialaccuracy = 1的每个block = 2的运行计数(condition = 1)重置为0,并将下一个增量恢复为1(不是之前的数字)
  • 对于每个trial,其中block != 2condition != 1将运行计数(cumulative)留作NA

这是一个最小的工作示例:

mydata <- data.frame(id = c(1,1,1,1,1,1,1,1,1,1,1),
                 age = c(1,1,1,1,1,1,1,1,1,1,2),
                 block = c(1,1,2,2,2,2,2,2,2,2,2),
                 trial = c(1,2,1,2,3,4,5,6,7,8,1),
                 condition = c(1,1,1,1,1,2,1,1,1,1,1),
                 accuracy = c(0,0,0,0,0,0,0,1,0,0,0)
)

id  age block   trial   condition   accuracy
1   1   1       1       1           0
1   1   1       2       1           0
1   1   2       1       1           0
1   1   2       2       1           0
1   1   2       3       1           0
1   1   2       4       2           0
1   1   2       5       1           0
1   1   2       6       1           1
1   1   2       7       1           0
1   1   2       8       1           0
1   2   2       1       1           0

预期的产出是:

id  age block   trial   condition   accuracy    cumulative
1   1   1       1       1           0           NA
1   1   1       2       1           0           NA
1   1   2       1       1           0           1
1   1   2       2       1           0           2
1   1   2       3       1           0           3
1   1   2       4       2           0           NA
1   1   2       5       1           0           4
1   1   2       6       1           1           0
1   1   2       7       1           0           1
1   1   2       8       1           0           2
1   2   2       1       1           0           1
r dplyr conditional cumulative-sum
2个回答
2
投票

我们可以使用case_when根据我们的条件分配我们需要的值。然后我们使用group_by添加额外的cumsum条件来切换temp列0时的值。在最后的mutate步骤中,我们暂时将replace中的NA temp值设置为0,然后将cumsum放在它上面并再次将NA值放回到它的位置以获得最终的输出。

library(dplyr)

mydata %>%
    group_by(id, age) %>%
    mutate(temp = case_when(accuracy == 0 & block == 2 & condition == 1 ~ 1, 
                            accuracy == 1 & block == 2 & condition == 1 ~ 0, 
                            TRUE ~ NA_real_)) %>%
    ungroup() %>%
    group_by(id, age, group = cumsum(replace(temp == 0, is.na(temp), 0))) %>%
    mutate(cumulative = replace(cumsum(replace(temp, is.na(temp), 0)),
                          is.na(temp), NA)) %>%
    select(-temp, -group)


#    group    id   age block trial condition accuracy cumulative
#   <dbl> <dbl> <dbl> <dbl> <dbl>     <dbl>    <dbl>      <dbl>
# 1     0     1     1     1     1         1        0         NA
# 2     0     1     1     1     2         1        0         NA
# 3     0     1     1     2     1         1        0          1
# 4     0     1     1     2     2         1        0          2
# 5     0     1     1     2     3         1        0          3
# 6     0     1     1     2     4         2        0         NA
# 7     0     1     1     2     5         1        0          4
# 8     1     1     1     2     6         1        1          0
# 9     1     1     1     2     7         1        0          1
#10     1     1     1     2     8         1        0          2
#11     1     1     2     2     1         1        0          1

2
投票

这是一个使用data.table的选项。创建一个二进制列,基于match使用自定义值的'precision','block','condition'的pasted值,按二进制列的运行长度id('ind'),'id'和'age',得到'ind'的累积和并将它(:=)分配给一个新列('累积')

library(data.table)
setDT(mydata)[, ind := match(do.call(paste0, .SD), c("121", "021")) - 1,
    .SDcols = c("accuracy", "block", "condition")
     ][, Cumulative := cumsum(ind), .(rleid(ind), id, age)
      ][, ind := NULL][]
#    id age block trial condition accuracy Cumulative
# 1:  1   1     1     1         1        0         NA
# 2:  1   1     1     2         1        0         NA
# 3:  1   1     2     1         1        0          1
# 4:  1   1     2     2         1        0          2
# 5:  1   1     2     3         1        0          3
# 6:  1   1     2     4         2        0         NA
# 7:  1   1     2     5         1        1          0
# 8:  1   1     2     6         1        0          1
# 9:  1   1     2     7         1        0          2
#10:  1   2     2     1         1        0          1
© www.soinside.com 2019 - 2024. All rights reserved.