Search code examples
rmatrixalternating

Alternate, interweave or interlace two matrices


I've got two matrices which I want to interweave/interlace/stack alternatively on top of each other/rbind in an alternating manner.

ranks=1:3
names=c("Karl", "Klaus", "Mary")
x <- cbind(ranks, names)

universities=c("Cape Town", "London", "Berlin")
y <- cbind(rep("", 3), universities)

After one row of x, I want one row of y:

     [,1] [,2]       
[1,] "1"  "Karl"     
[2,] ""   "Cape Town"
[3,] "2"  "Klaus"      
[4,] ""   "London"   
[5,] "3"  "Mary"   
[6,] ""   "Berlin" 

I tried matrix(rbind(x, y), ncol=2) (which seems to solve the problem if I had two strings) without effect


Solution

  • Here are two alternatives.

    First, assuming we have to start with "x" and "y", you can try interleave from the "gdata" package:

    library(gdata)
    interleave(x, y)
    #      ranks names      
    # [1,] "1"   "Karl"     
    # [2,] ""    "Cape Town"
    # [3,] "2"   "Klaus"    
    # [4,] ""    "London"   
    # [5,] "3"   "Mary"     
    # [6,] ""    "Berlin"
    

    Second, assuming we can start with "ranks", "names", and "universities", you can use base R, like this:

    cbind(c(t(cbind(ranks, ""))), c(t(cbind(names, universities))))
    #      [,1] [,2]       
    # [1,] "1"  "Karl"     
    # [2,] ""   "Cape Town"
    # [3,] "2"  "Klaus"    
    # [4,] ""   "London"   
    # [5,] "3"  "Mary"     
    # [6,] ""   "Berlin"
    

    A better alternative, however, would be to use something like melt (from "reshape2" or "data.table"). This would allow you to add another variable that indicates what type of measurement a value represents.

    library(data.table)
    melt(data.table(ranks, names, universities), "ranks")
    #    ranks     variable     value
    # 1:     1        names      Karl
    # 2:     2        names     Klaus
    # 3:     3        names      Mary
    # 4:     1 universities Cape Town
    # 5:     2 universities    London
    # 6:     3 universities    Berlin
    

    Or, to match your desired ordering:

    library(data.table)
    setorder(melt(data.table(ranks, names, universities), "ranks"), ranks)[]
    #    ranks     variable     value
    # 1:     1        names      Karl
    # 2:     1 universities Cape Town
    # 3:     2        names     Klaus
    # 4:     2 universities    London
    # 5:     3        names      Mary
    # 6:     3 universities    Berlin