2017-03-25 1 views
2

J'ai un cadre de données avec des réponses multiples de sujets (subid), qui se trouvent dans la colonne intitulée trials. Les essais comptent et recommencent dans un sujet.R Compteur conditionnel basé sur plusieurs colonnes

Voici un exemple dataframe:

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  

Je veux une colonne qui incrémente chaque épreuve du temps recommence au sein d'un sujet 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 

Les essais ne sont pas prévisibles dans où ils va recommencer. Ma solution jusqu'à présent est désordonnée et utilise une boucle for.

Solution:

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 

Cette solution ne démarre pas plus à une nouvelle subid. Avant d'arriver à ça, j'essayais d'utiliser le tidyverse de Wickham avec mute() et ifelse() dans une pipe. Si quelqu'un connaît un moyen d'accomplir cela avec ce paquet, je l'apprécierais. Cependant, je vais utiliser une solution de n'importe quel paquet. J'ai cherché environ un jour maintenant et ne pense pas que c'est une question en double à d'autres questions comme this.

+0

Oui, ce compterions jusqu'à chaque fois == 1 essai, mais il ne serait pas recommencer lorsque subid est passé de 1 à 2. –

+0

Mis à jour que dans la solution ci-dessous – akrun

+1

Merci, fonctionne parfaitement. –

Répondre

2

Nous pouvons le faire avec ave de base R

df$block <- with(df, ave(trial, subid, FUN = function(x) cumsum(x==1))) 

Ou avec dplyr

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