Search code examples
rmatrix-indexing

How can I insert the values from a vector into a matrix using column-major order?


I want to insert a set of n values expressed as a vector into a corresponding set of locations in a matrix. The real-world application involves inserting a set of n sea surface temperature values into an image of a region that is represented as a grid with dimension nrow x ncol > n in for which I have identified the n water pixels that should receive the temperature values. The problem I've run into is that the temperature values are ordered as if they were from a column-major matrix rather than the row-major ordering used to index the R grid.

Here is a toy example of what I mean.

> grid <- matrix(0,4,4)
> grid                       # define the base grid
     [,1] [,2] [,3] [,4]
[1,]    0    0    0    0
[2,]    0    0    0    0
[3,]    0    0    0    0
[4,]    0    0    0    0

> temps <- c(9,9,9,9,9)     # we have 5 temperature values
> locs <- c(2,3,4,6,7)      # locations in the base grid that are water

> grid[locs] <- temps       # not really what I want - substitution in row-major order
> grid
     [,1] [,2] [,3] [,4]
[1,]    0    0    0    0
[2,]    9    9    0    0
[3,]    9    9    0    0
[4,]    9    0    0    0

The desired result would be rather:

     [,1] [,2] [,3] [,4]
[1,]    0    9    9    9
[2,]    0    9    9    0
[3,]    0    0    0    0
[4,]    0    0    0    0

I suppose I could play with transposing the grid, doing the substitution and then transposing it back, but I'd think there would be a better way to approach this problem.


Solution

  • Here are a couple of options, each of which works on matrices of arbitrary dimension:


    arrayIndByRow <- function(ind, dim) {
       arrayInd(ind, rev(dim))[,2:1]
    }
    
    grid[arrayIndByRow(locs, dim(grid))] <- temps
    grid
    #      [,1] [,2] [,3] [,4]
    # [1,]    0    9    9    9
    # [2,]    0    9    9    0
    # [3,]    0    0    0    0
    # [4,]    0    0    0    0
    

    f <- function(ind, dim) {
        nr <- dim[1]
        nc <- dim[2]
        ii <- ind - 1
        ((ii %/% nc) + 1) + nr*(ii %% nc)
    }
    
    grid[f(locs, dim(grid))] <- 1:5
    grid
    #      [,1] [,2] [,3] [,4]
    # [1,]    0    1    2    3
    # [2,]    0    4    5    0
    # [3,]    0    0    0    0
    # [4,]    0    0    0    0