Jose Quesada
Jose Quesada

Reputation: 69

how combine two list of dataframes by names

I have two list of dataframes, like:

names1 <- c("1", "2")
mydf1 <- data.frame(V1=c(1:2), V2=rep("A",2)) 
mydf2 <- data.frame(V1=c(1:3), V2=rep("B",3))
list1 <- list(mydf1,mydf2)

names2 <- c("1","1","2")
mydf4 <- data.frame(V1=c(1:3), V2=rep("BB",3)) 
mydf5 <- data.frame(V1=c(1:3), V2=rep("CC",3)) 
mydf6 <- data.frame(V1=c(1:3), V2=rep("DD",3)) 
list2 <- list(mydf4,mydf5,mydf6)

names(list1) <- names1
names(list2) <- names2

and I want combine into lists by equal names. I want something like that:

$`1`
  V1 V2
1  1  A
2  2  A
3  1 BB
4  2 BB
5  3 BB

$`1`
  V1 V2
1  1  A
2  2  A
3  1 CC
4  2 CC
5  3 CC

$'2'
  V1 V2
1  1  B
2  2  B
3  3  B
4  1 DD
5  2 DD
6  3 DD

I'd tried

mapply(rbind, list1, list2, SIMPLIFY=FALSE)

but the result is chaotic

any ideas? thanks!!

Upvotes: 1

Views: 907

Answers (2)

Rich Scriven
Rich Scriven

Reputation: 99331

When names are repeated in a subset, the corresponding variable is also repeated in the result. Using this fact, we can use match(), and then Map()

(m <- match(names(list2), names(list1), nomatch = 0L))
# [1] 1 1 2
Map(rbind, list1[m], list2)

which returns the desired list

List of 3
 $ 1:'data.frame':  5 obs. of  2 variables:
  ..$ V1: int [1:5] 1 2 1 2 3
  ..$ V2: Factor w/ 2 levels "A","BB": 1 1 2 2 2
 $ 1:'data.frame':  5 obs. of  2 variables:
  ..$ V1: int [1:5] 1 2 1 2 3
  ..$ V2: Factor w/ 2 levels "A","CC": 1 1 2 2 2
 $ 2:'data.frame':  6 obs. of  2 variables:
  ..$ V1: int [1:6] 1 2 3 1 2 3
  ..$ V2: Factor w/ 2 levels "B","DD": 1 1 1 2 2 2

Upvotes: 4

A5C1D2H2I1M1N2O1R2T1
A5C1D2H2I1M1N2O1R2T1

Reputation: 193527

Assuming that "list1" does not have duplicated names, but "list2" does (as in your example data), you might be able to create a helper function like the following to do the task:

stackMe <- function(x) {
  a <- eval.parent(quote(names(X)))[substitute(x)[[3]]]
  rbind(list1[[a]], x)
} 

The first line (borrowed from this answer) grabs the name of the list item being worked on. We can use that in the second line to access the relevant value from "list1".

Here's the result with this sample data:

lapply(list2, stackMe)
# $`1`
#   V1 V2
# 1  1  A
# 2  2  A
# 3  1 BB
# 4  2 BB
# 5  3 BB
# 
# $`1`
#   V1 V2
# 1  1  A
# 2  2  A
# 3  1 CC
# 4  2 CC
# 5  3 CC
# 
# $`2`
#   V1 V2
# 1  1  B
# 2  2  B
# 3  3  B
# 4  1 DD
# 5  2 DD
# 6  3 DD

Upvotes: 1

Related Questions