2015-01-14 2 views
15

Я пытаюсь выяснить, как получить все диагонали матрицы. Например, у меня есть следующая матрица: < - матрица (1: 16,4)Получить все диагональные векторы из матрицы

с помощью функции diag(A) вернет

[1] 1 6 11 16 

В дополнение к основной диагонали, я хотел бы список всех диагоналей выше и ниже.

5 10 15 
2 7 12 
9 14 
3 8 
4 
13 

Я нашел ссылку https://stackoverflow.com/a/13049722, которая дает мне диагонали непосредственно выше и ниже основной один, но я не могу показаться, чтобы выяснить, как продлить код, чтобы получить остальную часть их для любой матрицы размера. Я попробовал два вложенных цикла, так как кажется, что какой-то прирост матричных индексов даст результат, который я ищу. Я пробовал использовать ncol (A), nrow (A) в циклах for, но, похоже, не мог найти правильную комбинацию. Кроме того, я знаю, что для петли, как правило, с неодобрением в R.

Код дано было:

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

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

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

+0

Почему вы не смотрите на ответ @ GavinSimpson? – A5C1D2H2I1M1N2O1R2T1

+0

Я также прочитал этот ответ, поэтому я понимаю, что решение включает в себя увеличение в зависимости от количества строк и столбцов, однако как упаковать его как функцию, которая возвращает все диагонали в одной матрице, это то, что уклоняется от меня здесь. Я читал все ответы неоднократно. – Beaker

+4

Боковое примечание: петли 'for' не смущены. Это миф (ИМО). Они находятся по всему исходному коду. Они просто должны использоваться надлежащим образом, как и любая другая функция. :-) –

ответ

46
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 
+6

Отличный. вы выигрываете (+1) –

+5

Святое дерьмо! Это блестяще!Кажется, что он корректно работает и с неквадратичными матрицами. – Beaker

+5

и может быть изменен для обратных диагоналей 'строка (A) + col (A)' – user20650

4

Поскольку вы имеете дело с квадратными матрицами, должно быть очень просто преобразовать ответ Гэвина в небольшую функцию, которая сначала вычисляет диапазон, который следует использовать в качестве значений смещения. Вот такая функция:

Вот результат на вашей матрице образцов «А».

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 
Смежные вопросы