Как я могу вставить значения из вектора в матрицу, используя порядок столбцов?

Я хочу вставить набор из n значений, выраженных в виде вектора, в соответствующий набор местоположений в матрице. Реальное приложение включает в себя вставку набора из n значений температуры поверхности моря в изображение области, представленной в виде сетки с размером nrow x ncol> n, для которого я определил n пикселей воды, которые должны получить значения температуры. . Проблема, с которой я столкнулся, заключается в том, что значения температуры упорядочены так, как если бы они были из основной матрицы столбцов, а не из основного порядка строк, используемого для индексации R-сетки.

Вот игрушечный пример того, что я имею в виду.

> 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

Желаемый результат был бы скорее:

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

Полагаю, я мог бы поиграть с транспонированием сетки, выполнением замены, а затем транспонированием ее обратно, но я думаю, что есть лучший способ подойти к этой проблеме.


person Fleetboat    schedule 05.11.2014    source источник


Ответы (4)


Вот несколько вариантов, каждый из которых работает с матрицами произвольной размерности:


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
person Josh O'Brien    schedule 06.11.2014
comment
Я почти уверен, что ваш второй вариант работает только для квадратных матриц (так как он такой же, как и мой внизу :)) ... Например, для матрицы 4 на 5 2 должно перейти к 6, но с указанной выше функцией f(2,c(4,5)) == 5. - person jed; 06.11.2014
comment
@jed - Нет, это не так. С матрицей 4x5 2 должно отображаться на 5. (Он ведет обратный отсчет до четырех элементов в первом столбце, а затем возвращается в верхнюю часть второго столбца, когда достигает пятого элемента). Попробуйте сами, чтобы убедиться, что это правильно, с grid <- matrix(0,nr=4,nc=5); grid[f(2, dim(grid))] <- 99; grid. Кроме того, извините, что я не видел и просто отредактировал ваш ответ, когда вернулся сюда, чтобы добавить свой очень похожий f - Я поставил +1 ваш, когда заметил его несколько часов назад! - person Josh O'Brien; 06.11.2014
comment
Ах да, я шел неправильным путем. Как и в 6, следует перейти к 2, что действительно происходит в вашей функции! - person jed; 06.11.2014

Если у вас есть квадратная матрица, вы можете написать небольшую функцию по модулю, которая заменяет ваши числа правильными:

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

Вы можете сделать это и с неквадратной матрицей, только это немного сложнее.

person jed    schedule 05.11.2014

Вы можете поработать с индексами. Сначала мы составляем последовательность длины матрицы по количеству столбцов. Затем мы итеративно добавляем 1 к последовательности. Мы делаем это для количества строк. Затем подмножество этого вектора для вектора местоположения даст нам местоположение в матрице.

x <- seq(1, length(grid), ncol(grid))
grid[sapply(0:(nrow(grid)-1), "+", x)[locs]] <- 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
person Rich Scriven    schedule 06.11.2014

Один из способов сделать это - создать новую матрицу с необходимыми данными, указав byrow=TRUE при ее создании. Для этого вам нужно создать промежуточный вектор для хранения и изменения данных grid:

grid <- matrix(rep(0,16),ncol=4)
##
temps <- c(9,9,9,9,9)     
locs <- c(2,3,4,6,7)      
##
#vgrid <- as.numeric(grid)
vgrid <- c(grid)
vgrid[locs] <- temps
##
> matrix(vgrid,ncol=ncol(grid),byrow=TRUE)
     [,1] [,2] [,3] [,4]
[1,]    0    9    9    9
[2,]    0    9    9    0
[3,]    0    0    0    0
[4,]    0    0    0    0
person nrussell    schedule 05.11.2014
comment
Просто любопытно, почему as.numeric(grid)? grid уже числовой. Вы можете использовать c(grid), чтобы свернуть матрицу - person Rich Scriven; 06.11.2014