R条件计数器基于多列

时间:2017-03-25 18:33:09

标签: r loops dataframe increment tidyverse

我有一个数据框,其中包含来自主题(subid)的多个回复,这些回复位于标记为试验的列中。试验计数,然后在一个主题内重新开始。

以下是一个示例数据框:

subid <- rep(1:2, c(10,10))
trial <- rep(1:5, 4)
response <- rnorm(20, 10, 3)

df <- as.data.frame(cbind(subid,trial, response))
df

   subid trial  response
1      1     1  3.591832   
2      1     2  8.980606     
3      1     3 12.943185     
4      1     4  9.149388     
5      1     5 10.192392     
6      1     1 15.998124     
7      1     2 13.288248     

我想要一个在每次试验开始时在一个主题ID(subid)内增加的列:

df$block <- c(rep(1:2, c(5,5)),rep(1:2, c(5,5)))
df
     subid trial response block
1      1     1  3.591832     1
2      1     2  8.980606     1
3      1     3 12.943185     1
4      1     4  9.149388     1
5      1     5 10.192392     1
6      1     1 15.998124     2
7      1     2 13.288248     2

试验在他们重新开始的地方是不可预测的。到目前为止,我的解决方案是凌乱的,并使用for循环。

解决方案:

block <- 0
blocklist <- 0

for (i in seq_along(df$trial)){
   if (df$trial[i]==1){
     block = block + 1}else
   if (df$trial!=1){
     block = block}
  blocklist<- c(blocklist, block)
}

blocklist <- blocklist[-1]
df$block <- blocklist

此解决方案不会在新的subid处重新开始。在我谈到这个之前,我试图在管道中使用Wickham的tidyverse与mutate()和ifelse()。如果有人知道用这个包完成这个的方法我会很感激。但是,我将使用任何软件包中的解决方案。我现在搜索了大约一天,并且不认为这是其他问题的重复问题,例如this

1 个答案:

答案 0 :(得分:2)

我们可以使用ave

中的base R执行此操作
df$block <- with(df, ave(trial, subid, FUN = function(x) cumsum(x==1)))

dplyr

library(dplyr)
df %>%
   group_by(subid) %>%
   mutate(block = cumsum(trial==1))