2017-03-25 39 views
2

我有一个数据框,其中有多个来自主题(subid)的响应,这些响应位于标记为试验的列中。试验计数并在一个主题内重新开始。R基于多列的条件计数器

下面是一个例子数据框:

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(子编号)内开始在列:

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 

这种解决方案并不在一个新的子编号开始。在我来到这之前,我试图在管道中使用Wickham的mutate()和ifelse()。如果有人知道一种方法来完成这个包,我将不胜感激。不过,我会使用任何软件包中的解决方案。我已经搜索了大约一天,并且不认为这是对this等其他问题的重复问题。

+0

是的,这将每次试验== 1计数,但它不会重新开始当subid从1变为2. –

+0

在下面的解决方案中更新了 – akrun

+1

谢谢,完美地工作。 –

回答

2

我们可以从avebase 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))