Home > Software engineering >  Naming list elements as they go through a loop
Naming list elements as they go through a loop

Time:01-18

As mentioned in my previous question from a couple of days ago (Pairwise t test loop through dataframes contained in a list) , I have a large dataframe which can be mimicked by:

exampledf <- data.frame(Item = c("A", "B", "C", "A", "B", "C", "A", "B", "C"), 
             Value=runif(9), 
             Condition=c("Control","Control","Control", "Test", "Test", "Test",  "Placebo", "Placebo", "Placebo"))

I split this df into a list by filtering for Item A, Item B, Item C, etc. using dplyr

Listdf <- split(exampledf, Item)

I got help on my previous question looping through a pairwise.t.test within these individual dataframes, so for example doing a pairwise comparison of the measured values between the different conditions for Item A. The code I use looks like this:

p <-list() 
for (i in 1:length(Listdf)) {
  p[[i]] <- pairwise.t.test(Listdf[[i]]$Value, Listdf[[i]]$Condition, p.adjust = "none")
}
p

I also got the suggestion of the code:

lapply(1:length(Listdf), function(x) {pairwise.t.test(Listdf[[x]]$Value, Listdf[[x]]$Condition, p.adjust = "none")})

My problem now is that both of these options do loop through and perform the t.tests, which they spit out into the p list. However, the name of the "i" so in this case which Item pertains to which pairwise.t.test result in the p list is lost.

I tried this approach using lapply and defining a function which keeps the names but it did not work and just spat out the same p list as before:

lapply_preserve_names <- function(list, fun){
  lapply(seq_along(list), function(i) {
    obj = list[i]
    names(obj) = names(list)[i]
    fun(obj)
  })
}
p_names <- lapply_preserve_names(1:length(Listdf), function(x) {pairwise.t.test(Listdf[[x]]$Value, Listdf[[x]]$Condition, p.adjust = "none")})

I also tried

for (i in 1:length(Listdf)) {
  assign(paste("Pvalue", i, sep = "_"), pairwise.t.test(Listdf[[i]]$Value, Listdf[[i]]$Condition, p.adjust = "none"))
}

and

for (i in 1:length(Listdf)) {
  p[[i]] <- pairwise.t.test(Listdf[[i]]$Value, Listdf[[i]]$Condition, p.adjust = "none")
  assign(paste("Pvalue", i, sep = "_"), Listdf[[i]]$Item))
}

I believe the crux of my problem is the combining of the assign function with the previously described loop, which generates the list p. Does anyone have an idea how this could be done more efficiently/correctly?

I also wonder if there is a way to gather the results within the list into a sort of plot, kind of like a facet wrapped ggplot but with the table containing the p-values rather than individual plots.

I would be very grateful for any suggestions or hints you might be able to offer!

CodePudding user response:

When one performs the split, the elements in the list are named. It is possible to extract that list of names and assign it to the results of the pairwise statement.

Would names(p) <- names(Listdf) work for you.

#create sample data
exampledf <- data.frame(Item = c("A", "B", "C", "A", "B", "C", "A", "B", "C"), 
                        Condition=c("Control","Control","Control", "Test", "Test", "Test",  "Placebo", "Placebo", "Placebo"))

exampledf <- rbind(exampledf, exampledf)
exampledf$Value=runif(18)

library(broom)
#split
Listdf <- split(exampledf, exampledf$Item)

#perform calculation
p<-lapply(Listdf, function(x) {
   broom::tidy(pairwise.t.test(x$Value, x$Condition, p.adjust = "none"))})

names(p)<-names(Listdf)

#create a trable of pvalues
#assumes table is in the same order for each list element
answer<-p[[1]][,1:2]
for (name in names(p)) {
   answer[[name]]<-p[[name]][,"p.value"]
}
answer
# A tibble: 3 × 5
  group1  group2  A$p.value B$p.value C$p.value
  <chr>   <chr>       <dbl>     <dbl>     <dbl>
1 Placebo Control    0.168      0.666     0.883
2 Test    Control    0.0772     0.434     0.439
3 Test    Placebo    0.0210     0.701     0.519
  •  Tags:  
  • Related