Search code examples
rlistmergeconcatenation

Combine dataframes in two different lists keyed on the element name in R


I have two lists list1 and list2 each of which contain dataframes or datatables which are uniquely identified by their name. I would like to combine the list1 and list2 keyed on the name of the dataset. I want the elements of both the lists to be present in the combined list. I have tried a lot of solutions from stackoverflow like do.call(c, list1, list2), Map(c, list1, list2) or mapply, merge, list.join. The most success I got was by creating keys of the dataframe names and using Map with the keys but they did not retain the unmatched elements in the combined list, something like keys <- unique(c(names(list1), names(list2)) and combined_list <- Map(rbind, list1[keys], list2[keys]). But none of them work for me the way i want.

Basically i want to perform an rbind on the identically named datasets that are contained in the two lists. The lists may be of different length and have different elements and sometimes overlapping elements.

What the list1 and list2 look like:

a <- data.frame(id = 1:5, type =c("a", "b", "c", "d", "e"))
b <- data.frame(id = 6:10, type =c("f", "g", "h", "i", "j"))
c <- data.frame(id = 11:15, type =c("k", "l", "m", "n", "o"))

list1 <- list(a=a,b=b,c=c)

a <- data.frame(id = 16:20, type =c("p", "q", "r", "s", "t"))
b <- data.frame(id = 21:25, type =c("u", "v", "w", "x", "y"))
e <- data.frame(id = 26:30, type =c("z", "ab", "ac", "ad", "ae"))
f <- data.frame(id = 31:35, type =c("ba", "bb", "bc", "bd", "be"))

list2 <- list(a=a,b=b,e=e, f=f)

and the expected result should be like this:

a <- data.frame(id = c(1:5, 16:20), type =c("a", "b", "c", "d", "e", "p", "q", "r", "s", "t"))
b <- data.frame(id = c(6:10,21:25), type =c("f", "g", "h", "i", "j", "u", "v", "w", "x", "y"))
c <- data.frame(id = 11:15, type =c("k", "l", "m", "n", "o"))
e <- data.frame(id = 26:30, type =c("z", "ab", "ac", "ad", "ae"))
f <- data.frame(id = 31:35, type =c("ba", "bb", "bc", "bd", "be"))

combined_list <- list(a=a, b=b, c=c, e=e, f=f)

Greatly appreciate any response in this regard. P.S. This is my first post on SO. :)


Solution

  • You can try using the unique names from list1 and list2 as you have already tried and then use them to setnames:

    keys <- unique(c(names(list1), names(list2)))
    x <- setNames(Map(rbind, list1[keys], list2[keys]), keys)
    identical(x, combined_list)
    #[1] TRUE
    

    or using lapply:

    x <- lapply(setNames(keys, keys), function(x) {rbind(list1[[x]], list2[[x]])})
    identical(x, combined_list)
    #[1] TRUE