2017-04-15 119 views
1

我有一个列表的列表,我想将它转换成矩阵,使每列=一个子列表。列表到矩阵

莫克例如

list1 <- list(1, 2) 
list2 <- list(1, 2, 3) 
list3 <- list(1, 2, 3, 4) 

list_lists <- list (list1, list2, list3) 

我第一egalizing所有子列表的长度(填充有如果需要空值),以使所有子列表具有最长的一个的长度。这是为了避免让R重复数据填充最终矩阵中的行(如果我可以跳过此步骤,请随意)。

max_length <- max(unlist(lapply (list_lists, FUN = length))) 
list_lists <- lapply (list_lists, function (x) {length (x) <- max_length; return (x)}) 

我最好的尝试到目前为止

mat <- lapply (list_lists, cbind) 

mat不看表面像什么,我想,但实际上并非如此。这不是一个矩阵(并试图将它转换成一个使用as.matrix是不成功的),我不能像列表/矩阵一样引用列/行。

我期待

 [,1] [,2] [,3] 
[1,] 1 1 1 
[2,] 2 2 2 
[3,] NULL 3 3 
[4,] NULL NULL 4 

什么是怪我是

mat <- cbind (list_lists[[1]], list_lists[[2]], list_lists[[3]]) 

似乎工作。我敢打赌,这两条线是相同的,他们怎么会有所不同?

回答

1

使用sapply而不是lappy上是这样的:

list_lists <- sapply (list_lists, function (x) {length (x) <- max_length; return (x)}) 

这应该给你你想要的矩阵。似乎sapply会递归地取消列表list_lists中的每个列表,然后应用您指定的函数并将所有输出包装到矩阵中,从而有效地绕过上面指定的其他行。

4

他们是不同的,lapply返回一个列表,从摘录见下文从文档

使用do.call,而不是mat <- lapply (list_lists, cbind)如下:

mat <- do.call("cbind",list_lists) 

do.call是一样cbind (list_lists[[1]], list_lists[[2]], list_lists[[3]]),它发生对一系列将成为数据帧列的列表进行操作。

> do.call("cbind",list_lists) 
    [,1] [,2] [,3] 
[1,] 1 1 1 
[2,] 2 2 2 
[3,] NULL 3 3 
[4,] NULL NULL 4 
> 

理解do.call:

从技术文档:

do.call构建和执行从名称的函数调用或 功能和参数列表被传递给它。

lapply返回相同的长度为X,其中的每一个是 施加FUN到

搜索ř控制台上?do.call?lapply

X的相应元素的结果元素的列表

您还可以阅读:do.calllapply

1

stri_list2matrix功能应该能够处理这个问题:

library(stringi) 
stri_list2matrix(list_lists) 
##  [,1] [,2] [,3] 
## [1,] "1" "1" "1" 
## [2,] "2" "2" "2" 
## [3,] NA "3" "3" 
## [4,] NA NA "4" 

另一种方法是使用 “MAX_LENGTH” 创建矩阵:

ml <- max(lengths(list_lists)) 
do.call(cbind, lapply(list_lists, function(x) `length<-`(unlist(x), ml))) 
##  [,1] [,2] [,3] 
## [1,] 1 1 1 
## [2,] 2 2 2 
## [3,] NA 3 3 
## [4,] NA NA 4 

第三种选择是使用melt从 “reshape2”:

library(reshape2) 
dcast(melt(list_lists), L2 ~ L1) 
## L2 1 2 3 
## 1 1 1 1 1 
## 2 2 2 2 2 
## 3 3 NA 3 3 
## 4 4 NA NA 4