Получить все диагональные векторы из матрицы
Я пытаюсь понять, как получить все диагонали матрицы.
Например, скажем, у меня есть следующая матрица:
A < матрица (1:16,4)
используя функцию diag(A)
, вернет
[1] 1 6 11 16
В дополнение к первичной диагонали, мне нужен список всех диагоналей выше и ниже.
5 10 15
2 7 12
9 14
3 8
4
13
Я нашел следующую ссылку qaru.site/info/355910/..., которая дает мне диагонали непосредственно выше и ниже первичной, однако я не могу понять, как расширить код чтобы получить остальную часть для любой матрицы размера. Я попробовал два вложенных цикла, так как кажется, что какой-то прирост матричных индексов даст результат, который я ищу. Я пробовал использовать ncol (A), nrow (A) в циклах for, но, похоже, не мог найти правильную комбинацию. Плюс я знаю, что для циклов, как правило, неодобрительно в R.
Указанный код:
diag(A[-4,-1])
diag(A[-1,-4])
который возвратил две диагонали, как верхние, так и нижние
Конечно, это квадратная матрица, и не все матрицы, которые я хочу выполнить, будут квадратными. В случае необходимости заполнение неквадратной площади НО. Ответ, который мне нужен, может быть в одном из других ответов на странице, но исходный вопрос включает в себя средства, суммы и т.д., Которые добавили уровень сложности, превышающий то, что я пытаюсь сделать. У меня такое чувство, что решение этого будет смехотворно простым, но для меня это просто не происходит. Я также удивлен, что я не мог найти этот вопрос нигде на SO, это, казалось бы, довольно распространенный вопрос. Возможно, я не знаю правильной терминологии для этой проблемы.
Ответы
Ответ 1
A <- matrix(1:16, 4)
# create an indicator for all diagonals in the matrix
d <- row(A) - col(A)
# use split to group on these values
split(A, d)
#
# $`-3`
# [1] 13
#
# $`-2`
# [1] 9 14
#
# $`-1`
# [1] 5 10 15
#
# $`0`
# [1] 1 6 11 16
#
# $`1`
# [1] 2 7 12
#
# $`2`
# [1] 3 8
#
# $`3`
# [1] 4
Ответ 2
Поскольку вы имеете дело с квадратными матрицами, должно быть очень легко преобразовать ответ Gavin в небольшую функцию, которая сначала вычисляет диапазон, который следует использовать в качестве значений смещения. Здесь такая функция:
AllDiags <- function(inmat, sorted = TRUE) {
Range <- ncol(inmat) - 1
Range <- -Range:Range
if (isTRUE(sorted)) Range <- Range[order(abs(Range))]
lapply(Range, function(x) {
inmat[row(inmat) == (col(inmat) - x)]
})
}
Здесь вывод на вашей матрице образцов "A".
AllDiags(A)
# [[1]]
# [1] 1 6 11 16
#
# [[2]]
# [1] 2 7 12
#
# [[3]]
# [1] 5 10 15
#
# [[4]]
# [1] 3 8
#
# [[5]]
# [1] 9 14
#
# [[6]]
# [1] 4
#
# [[7]]
# [1] 13
Ответ 3
Вот одно решение, основанное на наблюдении, что вы можете получить все диагонали, сокращая и расширяя матрицу. Сначала рассмотрим строку N col 1 (получить diag), затем строки (N-1): и cols (1: 2). Получите диагональ этого. и т.д..
N <- ncol(A)
rows <- cbind(c(N:1, rep(1,N-1)), c(rep(N,N), (N-1):1)) # row indeces
cols <- apply(rows, 2, rev) # col indeces
diagMatSubset <- function(mat, i1, i2, j1, j2) diag(mat[i1:i2, j1:j2, drop=FALSE])
Map(diagMatSubset, list(A), rows[,1], rows[,2], cols[,1], cols[,2])
[[1]]
[1] 4
[[2]]
[1] 3 8
[[3]]
[1] 2 7 12
[[4]]
[1] 1 6 11 16
[[5]]
[1] 5 10 15
[[6]]
[1] 9 14
[[7]]
[1] 13