Spencer Castro
Spencer Castro

Reputation: 1415

R Conditional Counter based on multiple columns

I have a data frame with multiple responses from subjects (subid), which are in the column labelled trials. The trials count up and then start over within one subject.

Here's an example 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     

I want a column that increments every time trial starts over within one subject 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

The trials are not predictable in where they will start over. My solution so far is messy and utilizes a for loop.

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

This solution does not start over at a new subid. Before I came to this I was attempting to use Wickham's tidyverse with mutate() and ifelse() in a pipe. If somebody knows a way to accomplish this with that package I would appreciate it. However, I'll use a solution from any package. I've searched for about a day now and don't think this is a duplicate question to other questions like this.

Upvotes: 2

Views: 595

Answers (1)

akrun
akrun

Reputation: 886998

We can do this with ave from base R

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

Or with dplyr

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

Upvotes: 2

Related Questions