【问题标题】:Converting Unsymmetric Vector-List into Matrix将非对称向量列表转换为矩阵
【发布时间】:2014-12-22 08:00:05
【问题描述】:

如何以高效的方式将列表对象(不同长度)转换为矩阵对象!以下示例阐明了上述目标:

假设你有一个结构的列表对象:

l <- list(c(1,2), c(5,7,3,11))
print(l)

# [[1]]
# [1] 1 2

# [[2]]
# [1]  5  7  3 11

目的是获取矩阵或data.frame的形式:

     [,1] [,2] [,3] [,4]
[1,]    1    2   NA   NA
[2,]    5    7    3   11

用 for 循环很容易解决这个问题。您有什么想法,如何轻松进行这种转换?提前谢谢!

【问题讨论】:

    标签: r list matrix


    【解决方案1】:

    你也可以试试

    t(sapply(l, `length<-`, max(sapply(l, length))))
    #     [,1] [,2] [,3] [,4]
    #[1,]    1    2   NA   NA
    #[2,]    5    7    3   11
    

    【讨论】:

      【解决方案2】:

      这是一种方法:

      n <- max(sapply(l, length))
      t(sapply(l, function(x) if(length(x) < n) c(x, rep(NA, n - length(x))) else x))
      
           [,1] [,2] [,3] [,4]
      [1,]    1    2   NA   NA
      [2,]    5    7    3   11
      

      首先我们找出每个列表元素的最大向量长度并将其存储在n(在本例中为 4)。

      然后,我们sapply遍历列表并检查列表元素的长度是否等于n,如果是,则返回它,如果它小于n,则返回列表元素+ NA重复和长度的差异一样频繁。这将返回一个矩阵。我们在该矩阵上使用t() 对其进行转置并获得所需的结果。

      【讨论】:

        【解决方案3】:

        如果您愿意使用包,您还可以考虑使用“stringi”包中的stri_list2matrix

        library(stringi)
        l <- list(c(1,2), c(5,7,3,11))
        stri_list2matrix(l, byrow = TRUE)
        #      [,1] [,2] [,3] [,4]
        # [1,] "1"  "2"  NA   NA  
        # [2,] "5"  "7"  "3"  "11"
        

        关于您关于高效执行此操作的问题,@akrun 的回答已经非常有效,但可以通过使用 vapply 而不是 sapply 来提高效率。 “stringi”方法也非常有效(并且具有不使用像length&lt;- 这样的神秘代码的好处)。

        funDD <- function() {
          n <- max(sapply(l, length))
          t(sapply(l, function(x) if(length(x) < n) c(x, rep(NA, n - length(x))) else x))
        }
        
        funAK <- function() t(sapply(l, `length<-`, max(sapply(l, length))))
        
        funAM <- function() {
          x <- max(vapply(l, length, 1L))
          t(vapply(l, `length<-`, numeric(x), x))
        } 
        
        funStringi <- function() stri_list2matrix(l, byrow = TRUE)
        
        ## Make a big list to test on
        set.seed(1)
        l <- lapply(sample(3:10, 1000000, TRUE), function(x) sample(10, x, TRUE))
        
        system.time(out1 <- funDD())
        #    user  system elapsed 
        #    5.81    0.33    7.02 
        
        library(microbenchmark)
        microbenchmark(funAK(), funAM(), funStringi(), times = 10)
        # Unit: seconds
        #          expr      min       lq     mean   median       uq      max neval
        #       funAK() 2.350877 2.499963 2.974141 3.123008 3.200545 3.418648    10
        #       funAM() 1.154151 1.238235 1.337607 1.287610 1.494964 1.508884    10
        #  funStringi() 2.080901 2.168248 2.352030 2.344763 2.462959 2.716910    10
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-01-30
          • 2014-03-09
          • 1970-01-01
          • 1970-01-01
          • 2018-03-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-30
          相关资源
          最近更新 更多