今天在工作中遇到一个问题:当我用lapply处理完一个列表后,会得到结果列表。结果列表的某一列都是相同的索引,我需要把列表中每一个元素都根据索引合并到一个DataFrame中,该怎么操作?
比如结果列表是l。
l1 <- replicate(5,round(runif(10),3),simplify = F)
l2 <- replicate(5,sample(1:10,10),simplify = F)
l <- vector(mode = "list",length = 5)
for(i in 1:5){
l[[i]][[1]] <- l2[[i]]
l[[i]][[2]] <- l1[[i]]
l[[i]] <- data.frame(l[[i]])
names(l[[i]]) <- c("v1","v2")
}
l
## [[1]]
## v1 v2
## 1 10 0.515
## 2 9 0.398
## 3 7 0.822
## 4 3 0.347
## 5 4 0.293
## 6 8 0.937
## 7 6 0.270
## 8 1 0.256
## 9 2 0.649
## 10 5 0.607
##
## [[2]]
## v1 v2
## 1 5 0.053
## 2 10 0.977
## 3 4 0.115
## 4 8 0.887
## 5 6 0.175
## 6 3 0.991
## 7 7 0.915
## 8 2 0.815
## 9 1 0.558
## 10 9 0.071
##
## [[3]]
## v1 v2
## 1 6 0.284
## 2 7 0.838
## 3 2 0.423
## 4 1 0.846
## 5 10 0.442
## 6 8 0.241
## 7 3 0.690
## 8 5 0.020
## 9 4 0.671
## 10 9 0.096
##
## [[4]]
## v1 v2
## 1 5 0.645
## 2 9 0.156
## 3 4 0.286
## 4 10 0.373
## 5 2 0.029
## 6 7 0.204
## 7 1 0.342
## 8 6 0.796
## 9 8 0.913
## 10 3 0.714
##
## [[5]]
## v1 v2
## 1 9 0.511
## 2 5 0.266
## 3 7 0.809
## 4 3 0.897
## 5 8 0.900
## 6 6 0.441
## 7 4 0.689
## 8 1 0.954
## 9 10 0.950
## 10 2 0.334
比较常规的操作是写一个类似于Reduce的函数,用循环完成。
merge_reduce <- function(l,atts){
num <- length(l)
k <- l[[1]]
for(i in 2:num){
k <- merge(k,l[[i]],by=atts)
}
return(k)
}
merge_reduce(l,"v1")
## v1 v2.x v2.y v2.x v2.y v2
## 1 1 0.256 0.558 0.846 0.342 0.954
## 2 2 0.649 0.815 0.423 0.029 0.334
## 3 3 0.347 0.991 0.690 0.714 0.897
## 4 4 0.293 0.115 0.671 0.286 0.689
## 5 5 0.607 0.053 0.020 0.645 0.266
## 6 6 0.270 0.175 0.284 0.796 0.441
## 7 7 0.822 0.915 0.838 0.204 0.809
## 8 8 0.937 0.887 0.241 0.913 0.900
## 9 9 0.398 0.071 0.096 0.156 0.511
## 10 10 0.515 0.977 0.442 0.373 0.950
但是用循环完成,仍不是最优美的方式。
考虑使用泛函,写一个mege_list的闭包,可以提供一个bywhat的参数,然后再用Reduce递归使用merge_list。
merge_list <- function(bywhat){
function(df1,df2){
merge(df1,df2,by=bywhat)
}
}
Reduce(merge_list(bywhat = "v1"),l)
## v1 v2.x v2.y v2.x v2.y v2
## 1 1 0.256 0.558 0.846 0.342 0.954
## 2 2 0.649 0.815 0.423 0.029 0.334
## 3 3 0.347 0.991 0.690 0.714 0.897
## 4 4 0.293 0.115 0.671 0.286 0.689
## 5 5 0.607 0.053 0.020 0.645 0.266
## 6 6 0.270 0.175 0.284 0.796 0.441
## 7 7 0.822 0.915 0.838 0.204 0.809
## 8 8 0.937 0.887 0.241 0.913 0.900
## 9 9 0.398 0.071 0.096 0.156 0.511
## 10 10 0.515 0.977 0.442 0.373 0.950
在简单的几行代码中,运用到了闭包和Reduce的泛函,非常简洁优美。