Search code examples
rmatrixsparse-matrix

Create and populate the upper triangular matrix with a vector in R


I need to create a square matrix based on a vector of varying length where the indices of the vector populate the upper triangular only without recycling of the vector elements.

I tried the following R code:

# example vector (could be longer or shorter!)
v <- letters[1:8]
# calculate dimensions of square matrix
n <- ceiling((-1 + sqrt(1 + 8 * length(v))) / 2)
# create empty matrix
m <- matrix(NA, nrow=n, ncol=n)
# populate the matrix
m[lower.tri(m, diag=TRUE)] <- 1:length(v)
m <- t(m)

And the resulting matrix looks like that:

     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]   NA    5    6    7
[3,]   NA   NA    8    1
[4,]   NA   NA   NA    2

How can I populate the matrix in a way that only that part of the upper triangular is filled which does not require recycling of vector index elements?

     [,1] [,2] [,3] [,4]
[1,]    1    2    3    4
[2,]   NA   NA    5    6
[3,]   NA   NA   NA    7
[4,]   NA   NA   NA    8
  • no recycling of vector elements
  • use the full dimensions (columns/rows) of the square matrix (maximize lower left "patch of NAs")

Thanks alot for the help!


Solution

  • Something like this?

    f <- function(v) {
      n <- length(v)
      # number of rows of the square matrix
      m <- ceiling(sqrt(0.25 + 2*n) - 0.5)
      x <- array(NA, rep(m, 2))
      s <- pmin(m + 1L - row(x), col(x)) + pmax(m + 1L - row(x), col(x))/n + (m + 1L)*upper.tri(x)
      x[sort(order(s)[1:n])] <- v
      t(x)
    }
    

    Testing vectors up to length 14:

    lapply(1:14, \(i) f(1:i))
    #> [[1]]
    #>      [,1]
    #> [1,]    1
    #> 
    #> [[2]]
    #>      [,1] [,2]
    #> [1,]    1    2
    #> [2,]   NA   NA
    #> 
    #> [[3]]
    #>      [,1] [,2]
    #> [1,]    1    2
    #> [2,]   NA    3
    #> 
    #> [[4]]
    #>      [,1] [,2] [,3]
    #> [1,]    1    2    3
    #> [2,]   NA   NA    4
    #> [3,]   NA   NA   NA
    #> 
    #> [[5]]
    #>      [,1] [,2] [,3]
    #> [1,]    1    2    3
    #> [2,]   NA   NA    4
    #> [3,]   NA   NA    5
    #> 
    #> [[6]]
    #>      [,1] [,2] [,3]
    #> [1,]    1    2    3
    #> [2,]   NA    4    5
    #> [3,]   NA   NA    6
    #> 
    #> [[7]]
    #>      [,1] [,2] [,3] [,4]
    #> [1,]    1    2    3    4
    #> [2,]   NA   NA   NA    5
    #> [3,]   NA   NA   NA    6
    #> [4,]   NA   NA   NA    7
    #> 
    #> [[8]]
    #>      [,1] [,2] [,3] [,4]
    #> [1,]    1    2    3    4
    #> [2,]   NA   NA    5    6
    #> [3,]   NA   NA   NA    7
    #> [4,]   NA   NA   NA    8
    #> 
    #> [[9]]
    #>      [,1] [,2] [,3] [,4]
    #> [1,]    1    2    3    4
    #> [2,]   NA    5    6    7
    #> [3,]   NA   NA   NA    8
    #> [4,]   NA   NA   NA    9
    #> 
    #> [[10]]
    #>      [,1] [,2] [,3] [,4]
    #> [1,]    1    2    3    4
    #> [2,]   NA    5    6    7
    #> [3,]   NA   NA    8    9
    #> [4,]   NA   NA   NA   10
    #> 
    #> [[11]]
    #>      [,1] [,2] [,3] [,4] [,5]
    #> [1,]    1    2    3    4    5
    #> [2,]   NA   NA    6    7    8
    #> [3,]   NA   NA   NA   NA    9
    #> [4,]   NA   NA   NA   NA   10
    #> [5,]   NA   NA   NA   NA   11
    #> 
    #> [[12]]
    #>      [,1] [,2] [,3] [,4] [,5]
    #> [1,]    1    2    3    4    5
    #> [2,]   NA   NA    6    7    8
    #> [3,]   NA   NA   NA    9   10
    #> [4,]   NA   NA   NA   NA   11
    #> [5,]   NA   NA   NA   NA   12
    #> 
    #> [[13]]
    #>      [,1] [,2] [,3] [,4] [,5]
    #> [1,]    1    2    3    4    5
    #> [2,]   NA    6    7    8    9
    #> [3,]   NA   NA   NA   10   11
    #> [4,]   NA   NA   NA   NA   12
    #> [5,]   NA   NA   NA   NA   13
    #> 
    #> [[14]]
    #>      [,1] [,2] [,3] [,4] [,5]
    #> [1,]    1    2    3    4    5
    #> [2,]   NA    6    7    8    9
    #> [3,]   NA   NA   NA   10   11
    #> [4,]   NA   NA   NA   12   13
    #> [5,]   NA   NA   NA   NA   14