R - 如何在交换列表元素时对两个列表进行rbind

时间:2017-09-06 00:59:54

标签: r

我想知道如何将包含向量的两个列表绑定到数据框中。 e.g。

a<-list(c(1,2,3,4,5), c(2,3,4,5,6))
b<-list(c(3,4,5,6,7), c(4,5,6,7,8))

如何从两个列表中创建数据框如下:

1 2 3 4 5
3 4 5 6 7
2 3 4 5 6 
4 5 6 7 8

所以我需要获取每个列表的第一个元素然后再绑定它们。然后取每个列表的第二个元素,然后rbind到前一个数据帧。我知道我可以使用for循环但是有更好更快的方法吗?

7 个答案:

答案 0 :(得分:4)

@DiscoSuperfly的答案可以解决长度不均匀的问题,例如:

a <- list(c(1,2,3,4,5), c(2,3,4,5,6), c(1,1,1,1,1))
b <- list(c(3,4,5,6,7), c(4,5,6,7,8))

答案:

L <- list(a,b)
L <- lapply(L, `length<-`, max(lengths(L)))
do.call(rbind, do.call(Map, c(rbind, L)))

#     [,1] [,2] [,3] [,4] [,5]
#[1,]    1    2    3    4    5
#[2,]    3    4    5    6    7
#[3,]    2    3    4    5    6
#[4,]    4    5    6    7    8
#[5,]    1    1    1    1    1

答案 1 :(得分:3)

使用purrr包的解决方案。

library(purrr)
map2_dfr(a, b, ~data.frame(rbind(.x, .y)))

  X1 X2 X3 X4 X5
1  1  2  3  4  5
2  3  4  5  6  7
3  2  3  4  5  6
4  4  5  6  7  8

答案 2 :(得分:2)

在给出的答案中,这似乎是使用两个列表时最快的,这在很大程度上要归功于@ thelatemail的建议编辑(谢谢!)。

试试这个:

rbab<-do.call(rbind,c(a,b)); rbind(rbab[c(TRUE,FALSE),],rbab[c(FALSE,TRUE),])

输出:

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    3    4    5    6    7
[3,]    2    3    4    5    6
[4,]    4    5    6    7    8

使用上面的c(TRUE,FALSE)每隔一行r和b;然后我们将其翻到c(FALSE,TRUE)以获得其余的。最后,我们一起讨论这个问题。

编辑:速度测试

这是一个更大规模的速度测试,用于客观比较,它使用两个6000个元素的列表,而不是原始的a和b。总共100次迭代用于估计这些统计数据。

#Sample used:
a<-list(c(1,2,3,4,5),c(2,3,4,5,6))
b<-list(c(3,4,5,6,7),c(4,5,6,7,8))
a<-a[rep(1:2,3e3)]
b<-a[rep(1:2,3e3)]

#Here is the collaboration version (with @thelatemail): 
func1 <- function(){
  rbab<-do.call(rbind,c(a,b)); rbind(rbab[c(TRUE,FALSE),],rbab[c(FALSE,TRUE),])
}

#Here is my original version: 
func2 <- function(){
  rbind(do.call(rbind,c(a,b))[c(TRUE,FALSE),],do.call(rbind,c(a,b))[c(FALSE,TRUE),])
}

#Here's a base-R translation of @ycw's answer (*translated by thelatemail)
func3 <- function(){
  do.call(rbind, Map(rbind, a, b))
}

#Here is @Onyambu's answer (also a great answer for its brevity!): 
func4 <- function(){
  Reduce(rbind,Map(rbind,a,b))
}

microbenchmark::microbenchmark(
  func1(),func2(),func3(),func4()
)

Unit: microseconds
    expr       min        lq      mean    median        uq       max neval
 func1()      4.39      6.46     14.74     15.85     20.24     31.94   100   
 func2()   5789.26   6578.83   7114.21   7027.57   7531.52   9411.05   100   
 func3()  10279.50  10970.70  11611.90  11245.47  11866.70  16315.00   100   
 func4() 251098.18 265936.30 273667.45 275778.04 281740.77 291279.20   100   

答案 3 :(得分:2)

set.seed(42)
x = floor(runif(n = 1000000, min = 1, max = 52 + 1))
plot(prop.table(table(x)), las = 2, cex.axis = 0.75)

答案 4 :(得分:1)

我创建了一个包含a和b的新列表,然后将其作为矩阵。我相信有更优雅的方法可以做到这一点。

a <- list(c(1,2,3,4,5), c(2,3,4,5,6), c(1,1,1,1,1))
b <- list(c(3,4,5,6,7), c(4,5,6,7,8))

# empty list
ab <- vector("list", length = length(a) + length(b)) 
# put a and b in correct locations 
ab[seq(1, length(ab), 2)] <- a
ab[seq(2, length(ab), 2)] <- b
# make the matrix
res <- t(matrix(unlist(ab), nrow=5, ncol=length(a) + length(b)))

答案 5 :(得分:0)

> ab <-rbind(unlist(a), unlist(b))
> ab <- rbind(ab[,1:5], ab[,6:10])
> ab
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    2    3    4    5
[2,]    3    4    5    6    7
[3,]    2    3    4    5    6
[4,]    4    5    6    7    8

答案 6 :(得分:0)

我愿意:

d <- t(as.data.frame(c(a,b))) rbind( d[ seq(1,nrow(d),by=2) ,] , d[ seq(2,nrow(d),by=2) ,])