Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 975
Fleetboat Avatar asked Nov 05 '14 21:11

Fleetboat


2 Answers

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
like image 138
Josh O'Brien Avatar answered Nov 03 '22 13:11

Josh O'Brien


If you have a square matrix, you could write a little modulo function that replaces your numbers with the correct ones:

new_num <- function(x,num_rows){
  x = x - 1
  row    <- x %/% num_rows
  column <- x %% num_rows
  newnum <- column * num_rows + row + 1
  return(newnum)
}

temps <- c(9,9,9,9,9)     
locs <- c(2,3,4,6,7)

new_locs <- new_num(locs,4)

M <- matrix(0,4,4)
M[new_locs] <- temps

You can do this with a non-square matrix too, it's just a bit harder.

like image 28
jed Avatar answered Nov 03 '22 13:11

jed