0

*note - since I am new to posting here I am also very open to feedback about how to make my questions more clear / better ways of generating example data / reproducible code etc.

I have a repeated measures data set that is currently in long format. Participants did a task in 9 seperate blocks, each block consists of 100 trials. Their reaction time, responses, and correctness were all measured.

There is one column that indicates which block of trials participants are on (labeled "display" in the attached photo.)

I want to keep the data in long form, but have seperate columns for the reaction time / correctness / response / etc for each block.So while I want to keep the data long, I want it to be wider.

Specifically, I want Trial.Number, Reaction .time, response, attempt, and correct to have seperate columns for each value of display (so 5 measures x 9 blocks = 45 new columns), but I still need there to be a row for each trial for each participant.

So there should be columns named block1.trialnumner - block9.trialnumber, block1.correct-block9.correct, and so on, and each participant should have 100 rows.

Here I have some code (feedback on how to produce fake data like this in a more efficient manner is also appreciated!)that generates a smaller data set that is conceptually the same as my actual data:

    set.seed(2222)
    Responses <- c('a','b','c','d')
    right <- c('1', '0')
    
    dat <- data.frame(ID = c("1", "1","1", "1", "1", "1","2","2","2", "2","2","2","3","3","3","3","3","3","4","4","4","4","4","4"),
                      condition = c("acq","acq","acq","acq","acq","acq","close","close","close","close","close","close","control","control","control","control","control","control","acq","acq","acq","acq","acq","acq"),
                      trial=rep(1:2),
                      reaction_time = runif(2),
                      response = sample(Responses, 4),
                      correct = sample(right, 2),
                      display = c("block 1","block 1", "block 2", "block 2","block 3","block 3","block 1","block 1", "block 2", "block 2","block 3","block 3","block 1","block 1", "block 2", "block 2","block 3","block 3","block 1","block 1", "block 2", "block 2","block 3","block 3" ))

This results in a data frame where each participant (i.e. ID) performed 3 blocks of trials (so a total of 6 unique rows per participant). The experimental condition (i.e., Condition) never changes for each individual, but all other columns change row to row.

In this example I would want 2 rows per participant (i.e., a row for each trial) and a seperate column for each block for reaction time, response, and correct (i.e., 3 blocks x 3 types of observations = 9 columns - block 1 reaction time, block 1 response, block 1 correct, block 2 reaction time, block 2 response, block 2, correct, and so on).

Below I have some code that is organized how I'd like this mock data set organized:

clean_dat <- data.frame(ID = c("1","1","2","2","3","3", "4", "4"),
                        condition = c("acq","acq","close", "close", "control", "control", "acq", "acq"),
                        trial = rep(1:2),
                        reaction_time_block1 = c("0.367658177" 
    ,"0.181875909", "0.756887668" ,"0.243691438" ,"0.576413027", 
    "0.927882617", "0.886305536", "0.573818437"),
                        reaction_time_block2 = c("0.826176795", 
    "0.584974443", "0.678065433", "0.062752954", "0.870914138", 
    "0.390425880", "0.985821178", "0.009305823"),
                        reaction_time_block3 =c("0.958869835", 
    "0.101798940", "0.376347888" ,"0.656183007" ,"0.975945541", 
    "0.986688076", "0.178954507" ,"0.764906755"),
                        response_block1 = c("a","b", "c","d","a","b", 
    "c","d"),
                        response_block2 = c("c","d","a","b" , 
    "c","d","a","b"),
                        response_block3 =c("a","b", "c","d","a","b", 
    "c","d"), 
                        correct_block1 = 
    c("0","1","0","1","0","1","0","1"),
                        correct_block2 
    =c("0","1","0","1","0","1","0","1") ,
                        correct_block3 
    =c("0","1","0","1","0","1","0","1"))

I have tried using pivot wider

dat_pivot <-dat %>% 
  pivot_wider(names_from = display, values_from = c(reaction_time, trial, response,correct))
  )

Which produces the correct number of columns, but only 1 row per participant (in this example there should be 2 rows per participant). Each pivoted column now contains a list (which should be expanded. Additionally this method produces the following error message: enter image description here

I've attempted using unlist(), but that hasn't worked.

At this point I'm thinking the easiest thing for me to do is to write a for-loop, but I think there has to be a way to do it that's easier than that.

  • 1
    Hi - welcome, please have a look at [How to make a great reproducible R example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). In general, provide example data, runnable code to reproduce the problem, and desired output (either as code that generates the output or in a formatted block that matches up with the example data. It's challenging to help you when your question is mostly text description. – andrew_reece Mar 17 '23 at 00:12
  • @andrew_reece Thank you for this - I'm in the process of updating my post to try and make it more clearer / easier to engage with. – captain broccoli heart Mar 17 '23 at 17:31
  • @andrew_reece I've done my best to make the question more reproducible - if there is anything more I could do please let me know! Thanks for your helpful comment! – captain broccoli heart Mar 17 '23 at 18:27
  • Hi! Does dat_pivot <- dat %>% pivot_wider(names_from = display, values_from = c(reaction_time, response,correct), id_cols = c(ID, trial)) do what you want? – Tob Mar 17 '23 at 18:35
  • @Tob This works on my 'fake' data and got me 95% of the way there on the real data (because I had not mentioned that on incorrect trials, participants get to repeat that trial, but including the variable 'Attempt' in the ID cols function seems to have done it! Thank you so much! – captain broccoli heart Mar 17 '23 at 19:21

1 Answers1

0

From what I can understand you want a row for each individual and each trial, and columns for the reaction time, response time and correct from each display. To do this you need to specify in pivot_wider which columns are the unique identifiers. Your code was almost correct but needed one change.

dat_pivot <- dat %>% 
  pivot_wider(names_from = display, 
  values_from = c(reaction_time, response, correct), 
  id_cols = c(ID, trial))

Tob
  • 245
  • 1
  • 9