1

I have set of data.frame object in nested list, I want to group them by name of data.frame object. Because each nested list, data.frame objects are placed in different order, I have difficulty to group them in new list. I tried transpose method from purr packages in CRAN, but it wasn't right answer that I expected. Does anyone knows any trick of doing this sort of grouping for data.frame object more efficiently? Thanks a lot

example:

res_1 <- list(con=list(a.con_1=airquality[1:4,], b.con_1=iris[2:5,], c.con_1=ChickWeight[3:7,]),
              dis=list(a.dis_1=airquality[5:7,], b.dis_1=iris[8:11,], c.dis_1=ChickWeight[12:17,]))

res_2 <- list(con=list(b.con_2=iris[7:11,], a.con_2=airquality[4:9,], c.con_2=ChickWeight[2:8,]),
              dis=list(b.dis_2=iris[2:5,], a.dis_2=airquality[1:3,], c.dis_2=ChickWeight[12:15,]))

res_3 <- list(con=list(c.con_3=ChickWeight[10:15,], a.con_3=airquality[2:9,], b.con_3=iris[12:19,]),
              dis=list(c.dis_3=ChickWeight[2:7,], a.dis_3=airquality[13:16,], b.dis_3=iris[2:7,]))

desired output:

group1_New <- list(con=list(a.con_1, a.con_2, a.con_3),
                   dis=list(a.dis_1, a.dis_2, a.dis_3))

group2_New <- list(con=list(b.con_1, b.con_2, b.con_3),
                   dis=list(b.dis_1, b.dis_2, b.dis_3))

group3_New <- list(con=list(c.con_1, c.con_2, c.con_3),
                   dis=list(c.dis_1, c.dis_2, c.dis_3))
  • 1
    It's easier to help you if you include a [reproducible example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). You should define all the variables included in your code so it can be copy/pasted into R to run and test. – MrFlick Jul 27 '16 at 15:02
  • I don't see any problem, I just tested in R. –  Jul 27 '16 at 15:19
  • Yes, that's right, in each list a, b, c are in different order for sure –  Jul 27 '16 at 15:28

1 Answers1

1

Here is a twice nested for loop that creates the desired structure. There is likely a more efficient method.

# put the nested lists into a list:
myList <- list(res_1, res_2, res_3)
# make a copy of the list to preserve the structure for the new list
myList2 <- myList

for(i in seq_len(length(myList))) {
  # get ordering of inner list names
  myOrder <- rank(names(myList[[c(i,2)]]))

  for(j in seq_len(length(myList[[i]]))) {
    for(k in seq_len(length(myList[[c(i, j)]]))) {
      # reorder content
      myList2[[c(myOrder[k], j, i)]] <- myList[[c(i, j, k)]]
      # rename element
      names(myList2[[c(myOrder[k], j)]])[i] <- names(myList[[c(i, j)]])[k]
    }
  }
}

If desired, you could extract the list items after the loops.

The key to this solution is the realization that if you put these lists into a list, the result can be achieved by selectively reversing the indices of the list items. By selectively, I mean that I incorporate rank on the data.frame names to find the proper order for the inner-most loop.

In addition to reordering the data.frames as desired, I included a line to properly reset the names within the list.

lmo
  • 37,904
  • 9
  • 56
  • 69
  • This is my idea: what if I reverse the order of res_2, res_3, then let them have same order of element like res_1 does, then using purrr packages to transpose accordingly. Is that possible? If Yes, How can I reverse back order? –  Jul 27 '16 at 15:49
  • your solution did not give me my desired output. Any idea? –  Jul 27 '16 at 15:51
  • 1
    See my edited version, which both reorders the data.frames and the list names. – lmo Jul 27 '16 at 16:33
  • your solution is wonderful. Thanks again for your kind favor. –  Jul 27 '16 at 17:46