取消列出具有矩阵元素到矩阵列表的列表

时间:2015-07-11 15:19:18

标签: r

假设A,B和C是矩阵。我有一个这样的列表:

  list(A,list(B,C))

我想将其转换为:

  list(A,B,C)

unlist函数将矩阵转换为向量!

例如:

A=matrix(1:10,nrow=2)
B=list(A,list(A,A))
unlist(B)

4 个答案:

答案 0 :(得分:13)

这是一个递归实现:

flatten2 <- function(X) if(is.list(X)) Reduce(c, lapply(X, flatten2)) else list(X)

然后:

str(flatten2(B))   # list of three matrices:
# List of 3
#  $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10
#  $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10
#  $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10

更复杂:

C <- list(A, list(list(A, A), A))
str(flatten2(C))
# List of 4
#  $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10
#  $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10
#  $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10
#  $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10

此外,一个“更多的”但更快的版本(这是皮埃尔测试的版本):

flatten <- function(X) {
  res <- list()
  for(i in X) res <- c(res, if(is.list(i)) Recall(i) else list(i))
  res
}

您可以通过将flatten2替换为Reduce来提高do.call的速度,但这有点不太可爱。 flatten即使有这种变化,仍然是最快的。

答案 1 :(得分:12)

你可以做这样的事情

delist<-function(x) {
    lists <- sapply(x, class)=="list"
    while(any(lists)) {
        x<-mapply(function(y,z) if (!z) list(y) else (y), x, lists, SIMPLIFY=FALSE)
        x<-do.call('c', x)
        lists <- sapply(x, class)=="list"
    }
    x
}

用你的例子得到

delist(B)
# [[1]]
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    1    3    5    7    9
# [2,]    2    4    6    8   10
# 
# [[2]]
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    1    3    5    7    9
# [2,]    2    4    6    8   10
# 
# [[3]]
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    1    3    5    7    9
# [2,]    2    4    6    8   10

答案 2 :(得分:7)

您可以使用rlist包的list.flatten功能。一个例子:

library(rlist)
A1 <- matrix(1:10, nrow = 2)
A2 <- matrix(11:20, nrow = 2)
A3 <- matrix(21:30, nrow = 2)
B <- list(A1, list(A2, A3))
C <- list.flatten(B)

C    
# [[1]]
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    1    3    5    7    9
# [2,]    2    4    6    8   10
# 
# [[2]]
#      [,1] [,2] [,3] [,4] [,5]
# [1,]   11   13   15   17   19
# [2,]   12   14   16   18   20
# 
# [[3]]
#      [,1] [,2] [,3] [,4] [,5]
# [1,]   21   23   25   27   29
# [2,]   22   24   26   28   30

str(C)    
# List of 3
#  $ : int [1:2, 1:5] 1 2 3 4 5 6 7 8 9 10
#  $ : int [1:2, 1:5] 11 12 13 14 15 16 17 18 19 20
#  $ : int [1:2, 1:5] 21 22 23 24 25 26 27 28 29 30

答案 3 :(得分:5)

这么多很棒的解决方案。我想做一个比较:

library(microbenchmark)
microbenchmark(
  flatten = flatten(lst),
  delist = delist(lst),
  list.flatten = list.flatten(lst))
#          expr     min       lq      mean   median       uq
#       flatten  14.606  16.3830  19.17356  17.7640  18.5540
#        delist 228.559 239.6115 251.52930 247.5070 254.0205
#  list.flatten  51.318  56.0545  63.87871  61.7785  70.2660
#      max neval
#   41.449   100
#  406.589   100
#  145.267   100

数据

A <- matrix(1e4, 100)
lst <- list(A, list(A, list(A, list(A, list(A, list(A, list(A)))))))
flatten <- function(X) {
  res <- list()
  for(i in X) res <- c(res, if(is.list(i)) Recall(i) else list(i))
  res
}

delist<-function(x) {
    lists <- sapply(x, class)=="list"
    while(any(lists)) {
        x<-mapply(function(y,z) if (!z) list(y) else (y), x, lists, SIMPLIFY=FALSE)
        x<-do.call('c', x)
        lists <- sapply(x, class)=="list"
    }
    x
}
library(rlist)
list.flatten