interleave rows of matrix stored in a list in R

后端 未结 2 534
情深已故
情深已故 2021-01-13 03:52

I want to create interleaved matrix from a list of matrices.

Example input:

> l <- list(a=matrix(1:4,2),b=matrix(5:8,2))
> l
$a
     [,1] [,         


        
相关标签:
2条回答
  • 2021-01-13 04:44

    Here is a one-liner:

    do.call(rbind, l)[order(sequence(sapply(l, nrow))), ]
    #      [,1] [,2]
    # [1,]    1    3
    # [2,]    5    7
    # [3,]    2    4
    # [4,]    6    8
    

    To help understand, the matrices are first stacked on top of each other with do.call(rbind, l), then the rows are extracted in the right order:

    sequence(sapply(l, nrow))
    # a1 a2 b1 b2 
    #  1  2  1  2 
    
    order(sequence(sapply(l, nrow)))
    # [1] 1 3 2 4
    

    It will work with any number of matrices and it will do "the right thing" (subjective) even if they don't have the same number of rows.

    0 讨论(0)
  • 2021-01-13 04:47

    Rather than reinventing the wheel, you can just modify it to get you to your destination.

    The interleave function from "gdata" starts with ... to let you specify a number of data.frames or matrices to put together. The first few lines of the function look like this:

    head(interleave)
    # 
    # 1 function (..., append.source = TRUE, sep = ": ", drop = FALSE) 
    # 2 {                                                              
    # 3     sources <- list(...)                                       
    # 4     sources[sapply(sources, is.null)] <- NULL                  
    # 5     sources <- lapply(sources, function(x) if (is.matrix(x) || 
    # 6         is.data.frame(x)) 
    

    You can just rewrite lines 1 and 3 as I did in this Gist to create a list version of interleave (here, I've called it Interleave)

    head(Interleave)
    #                                                                     
    # 1 function (myList, append.source = TRUE, sep = ": ", drop = FALSE) 
    # 2 {                                                                 
    # 3     sources <- myList                                             
    # 4     sources[sapply(sources, is.null)] <- NULL                     
    # 5     sources <- lapply(sources, function(x) if (is.matrix(x) ||    
    # 6         is.data.frame(x)) 
    

    Does it work?

    l <- list(a=matrix(1:4,2),b=matrix(5:8,2), c=matrix(9:12,2))
    Interleave(l)
    #   [,1] [,2]
    # a    1    3
    # b    5    7
    # c    9   11
    # a    2    4
    # b    6    8
    # c   10   12
    
    0 讨论(0)
提交回复
热议问题