How do I convert my code that transforms nested lists to a dataframe into a function?

Viewed 36

I have 18 lists, one for each condition. Inside a list of a condiction there are 10 lists, one for each participant. Within a list of a participant, there is a list with anywhere between 1 and 20 values of type double. To clarify, this is code to reproduce the list of one condition, remember I have 18 of these all slightly different.

Participant_List <- list()

for (i in 1:10) {
  Scores <- list()
  for (k in sample(1:5, replace = TRUE)) {
    Scores[[k]] <- sample(1:7, sample(1:10), replace = TRUE)
  }
  Participant_List[[i]] <- Scores

}

Now with some help, I got code to transform the list of one condition into a data frame in a long format:

#convert each participant's list to a data frame
x_dataframes <- lapply(seq_along(Participant_List), function(curParticipant){
  return(data.frame(Participant = curParticipant,
                    Score = unlist(Participant_List[[curParticipant]])))
})

#combine the list of dataframes into one dataframe
x_combined <- do.call("rbind", x_dataframes)

I would like to create a function containing this code to be able to simply apply this to the other conditions. I came up with the following, where I first create a list containing the conditions I have, called Hypo1_lists and then I feed this into the function below:

function(Hypo1_lists){
  
  #convert each participant's list to a data frame
  x_dataframe <- lapply(seq_along(Hypo1_lists), function(curParticipant){
    return(data.frame(Participant = curParticipant,
                     Score = unlist(Hypo1_lists[[curParticipant]])))
    
  #combine the list of dataframes into one dataframe
  Hypo1_lists <- do.call("rbind", x_dataframe) 
})
  
}

But this outputs one nested list...I want to store the outputs in separate data frames (one for each condition), the same I get from the code before I put it into a function.

1 Answers

You were mistakenly including the binding into the apply function.

myf <- function(Hypo1_lists){
  
  #convert each participant's list to a data frame
  x_dataframe <- lapply(seq_along(Hypo1_lists), function(curParticipant){
    return(data.frame(Participant = curParticipant,
                      Score = unlist(Hypo1_lists[[curParticipant]])))
  })
    #combine the list of dataframes into one dataframe
    Hypo1_lists <- do.call("rbind", x_dataframe) 

  return(Hypo1_lists)
}

myf(Participant_List)

    Participant Score
1             1     2
2             1     1
3             1     6
4             1     3

Also, don't forget to return something from your main function.


To apply this function to a nested list :

full <- list(Participant_List, Participant_List)
names(full) <- c("firstname", "secondname")
full_result <- lapply(full, myf)
summary(full_result)
           Length Class      Mode
firstname  2      data.frame list
secondname 2      data.frame list

To retrieve your second result for example, just use full_result[[2]] which is of class data.frame

Related