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

172
13

Я пытаюсь понять, как получить все диагонали матрицы.
Например, скажем, у меня есть следующая матрица:
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/questions/355910/..., которая дает мне диагонали непосредственно выше и ниже первичной, однако я не могу понять, как расширить код чтобы получить остальную часть для любой матрицы размера. Я попробовал два вложенных цикла, так как кажется, что какой-то прирост матричных индексов даст результат, который я ищу. Я пробовал использовать ncol (A), nrow (A) в циклах for, но, похоже, не мог найти правильную комбинацию. Плюс я знаю, что для циклов, как правило, неодобрительно в R.


Указанный код:


diag(A[-4,-1])
diag(A[-1,-4])

который возвратил две диагонали, как верхние, так и нижние


Конечно, это квадратная матрица, и не все матрицы, которые я хочу выполнить, будут квадратными. В случае необходимости заполнение неквадратной площади НО. Ответ, который мне нужен, может быть в одном из других ответов на странице, но исходный вопрос включает в себя средства, суммы и т.д., Которые добавили уровень сложности, превышающий то, что я пытаюсь сделать. У меня такое чувство, что решение этого будет смехотворно простым, но для меня это просто не происходит. Я также удивлен, что я не мог найти этот вопрос нигде на SO, это, казалось бы, довольно распространенный вопрос. Возможно, я не знаю правильной терминологии для этой проблемы.

спросил(а) 2021-01-19T18:23:15+03:00 2 месяца, 3 недели назад
1
Решение
295

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

ответил(а) 2021-01-19T18:23:15+03:00 2 месяца, 3 недели назад
96

Поскольку вы имеете дело с квадратными матрицами, должно быть очень легко преобразовать ответ 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

ответил(а) 2021-01-19T18:23:15+03:00 2 месяца, 3 недели назад
88

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

ответил(а) 2021-01-19T18:23:15+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема