I have a list of dataframes with different numbers of rows but a single id
set.seed(1)
f <- function(){
m <- matrix(1:40,ncol = 4, dimnames = list(NULL, paste0("x",1:4)))
m <- cbind.data.frame(id=1:10, m)
m[-sample(10,sample(9,1)),]
}
li <- lapply(1:5,\(x) f()) ; names(li) <- paste0("Obj ", 1:length(li))
li
$`Obj 1`
id x1 x2 x3 x4
6 6 6 16 26 36
$`Obj 2`
id x1 x2 x3 x4
2 2 2 12 22 32
3 3 3 13 23 33
4 4 4 14 24 34
6 6 6 16 26 36
7 7 7 17 27 37
8 8 8 18 28 38
10 10 10 20 30 40
$`Obj 3`
id x1 x2 x3 x4
2 2 2 12 22 32
3 3 3 13 23 33
4 4 4 14 24 34
8 8 8 18 28 38
$`Obj 4`
id x1 x2 x3 x4
6 6 6 16 26 36
$`Obj 5`
id x1 x2 x3 x4
1 1 1 11 21 31
4 4 4 14 24 34
5 5 5 15 25 35
7 7 7 17 27 37
9 9 9 19 29 39
10 10 10 20 30 40
I need to merge them all together
merged_df <- Reduce(\(x,y) merge(x, y, by = "id", all = T), li)
merged_df
id x1.x x2.x x3.x x4.x x1.y x2.y x3.y x4.y x1.x x2.x x3.x x4.x x1.y x2.y x3.y x4.y x1 x2 x3 x4
1 1 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 1 11 21 31
2 2 NA NA NA NA 2 12 22 32 2 12 22 32 NA NA NA NA NA NA NA NA
3 3 NA NA NA NA 3 13 23 33 3 13 23 33 NA NA NA NA NA NA NA NA
4 4 NA NA NA NA 4 14 24 34 4 14 24 34 NA NA NA NA 4 14 24 34
5 5 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 5 15 25 35
6 6 6 16 26 36 6 16 26 36 NA NA NA NA 6 16 26 36 NA NA NA NA
7 7 NA NA NA NA 7 17 27 37 NA NA NA NA NA NA NA NA 7 17 27 37
8 8 NA NA NA NA 8 18 28 38 8 18 28 38 NA NA NA NA NA NA NA NA
9 9 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA 9 19 29 39
10 10 NA NA NA NA 10 20 30 40 NA NA NA NA NA NA NA NA 10 20 30 40
And then return it back to the list while preserving the original names of the columns that were originally in the list and preserving the names of each list object that were originally.
How can I do that?
=========UPD========
here is my original list
$`Obj 1`
id x1 x2
1 1 1 4
3 3 3 6
$`Obj 2`
id x1 x2
2 2 2 5
3 3 3 6
I want to get this
$Obj1
id x1 x2
1 1 1 4
2 2 NA NA
3 3 3 6
$Obj2
id x1 x2
1 1 NA NA
2 2 2 5
3 3 3 6
I don't think this is a reduction, I suspect it's just enforcing all id
s in all frames.
lapply(li, merge,
data.frame(id = sort(unique(unlist(lapply(li, `[[`, "id"))))),
by = "id", all = TRUE)
# $`Obj 1`
# id x1 x2 x3 x4
# 1 1 NA NA NA NA
# 2 2 NA NA NA NA
# 3 3 NA NA NA NA
# 4 4 NA NA NA NA
# 5 5 NA NA NA NA
# 6 6 6 16 26 36
# 7 7 NA NA NA NA
# 8 8 NA NA NA NA
# 9 9 NA NA NA NA
# 10 10 NA NA NA NA
# $`Obj 2`
# id x1 x2 x3 x4
# 1 1 NA NA NA NA
# 2 2 2 12 22 32
# 3 3 3 13 23 33
# 4 4 4 14 24 34
# 5 5 NA NA NA NA
# 6 6 6 16 26 36
# 7 7 7 17 27 37
# 8 8 8 18 28 38
# 9 9 NA NA NA NA
# 10 10 10 20 30 40
# $`Obj 3`
# id x1 x2 x3 x4
# 1 1 NA NA NA NA
# 2 2 2 12 22 32
# 3 3 3 13 23 33
# 4 4 4 14 24 34
# 5 5 NA NA NA NA
# 6 6 NA NA NA NA
# 7 7 NA NA NA NA
# 8 8 8 18 28 38
# 9 9 NA NA NA NA
# 10 10 NA NA NA NA
# $`Obj 4`
# id x1 x2 x3 x4
# 1 1 NA NA NA NA
# 2 2 NA NA NA NA
# 3 3 NA NA NA NA
# 4 4 NA NA NA NA
# 5 5 NA NA NA NA
# 6 6 6 16 26 36
# 7 7 NA NA NA NA
# 8 8 NA NA NA NA
# 9 9 NA NA NA NA
# 10 10 NA NA NA NA
# $`Obj 5`
# id x1 x2 x3 x4
# 1 1 1 11 21 31
# 2 2 NA NA NA NA
# 3 3 NA NA NA NA
# 4 4 4 14 24 34
# 5 5 5 15 25 35
# 6 6 NA NA NA NA
# 7 7 7 17 27 37
# 8 8 NA NA NA NA
# 9 9 9 19 29 39
# 10 10 10 20 30 40