R(dplyr)中重置的条件运行计数(累积和)

R(dplyr)中重置的条件运行计数(累积和),r,dplyr,conditional,cumulative-sum,R,Dplyr,Conditional,Cumulative Sum,我试图计算一个以其他变量为条件的运行计数(即累积和),它可以重置另一个变量上的特定值。我在R工作,如果可能的话,我更喜欢基于dplyr的解决方案 我想根据以下算法为运行计数创建一个变量,cumulative: 在id和age 对于每个后续的试验,精度=0,块=2,条件=1 将每次试验的运行计数(累计值)重置为0,其中精度=1,块=2,条件=1,下一个增量恢复为1(不是上一个数字) 对于每个试验其中块!=2,或条件!=1,将运行计数(累计)保留为NA 下面是一个简单的工作示例: mydata

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

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

  • id
    age
  • 对于每个后续的
    试验,
    精度=0
    块=2
    条件=1
  • 将每次
    试验的运行计数(
    累计值
    )重置为0,其中
    精度=1
    块=2
    条件=1
    ,下一个增量恢复为1(不是上一个数字)
  • 对于每个
    试验
    其中
    块!=2
    ,或
    条件!=1
    ,将运行计数(
    累计
    )保留为
    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

我们可以在
时使用
case\u来根据我们的条件分配所需的值。然后,当
temp
列为0时,我们使用
cumsum
添加一个额外的
groupby
条件来切换值。在最后的
mutate
步骤中,我们临时将
temp
中的
NA
值替换为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
库(dplyr)
mydata%>%
组别(身份,年龄)%>%
当(精度==0和块==2和条件==1~1,
精度==1,块==2,条件==1~0,
真~NA_real(真)]>%
解组()%>%
分组依据(id、年龄、组=cumsum(替换(temp==0,is.na(temp),0)))%>%
突变(累积=替换(累积(替换(温度,为na(温度),0)),
is.na(温度),na))%>%
选择(-temp,-group)
#组id年龄段试验条件累积准确度
#                      
#1011010NA
#2 0 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
#6012420NA
# 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

这里有一个使用
数据表的选项。基于
匹配
创建一个二进制列,将
粘贴的
d值“精度”、“块”、“条件”与自定义值的值相匹配,按二进制列的运行长度id(“ind”)、“id”和“age”分组,获得“ind”的累计和,并将其分配给一个新列(“累计”)


我真的很喜欢这个答案。但是,它不能完全处理我的数据。我在数据中添加了一行(参见试验5)。如果你能解决这个问题,我很高兴给你一个正确的答案。谢谢大家!@谢谢你的耐心。我已经更新了答案,请看一看。这个答案很有趣,但与我的数据不完全一致。我在数据中添加了一行(参见试验5)。
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
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