Получить все диагональные векторы из матрицы

Я пытаюсь понять, как получить все диагонали матрицы. Например, скажем, у меня есть следующая матрица: 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