Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find offset diagonal of a matrix?

Tags:

r

Is there an easy way to extract a vector of an 'offset' and 'reverse' "diagonal" (the x's) of a matrix in R?

      [,1] [,2] [,3] [,4] [,5]
[1,]    x    0    0    0    0
[2,]    0    0    0    0    x
[3,]    0    0    0    x    0
[4,]    0    0    x    0    0
[5,]    0    x    0    0    0

I tried diag() but it does'nt seem to take any options..

like image 914
jenswirf Avatar asked May 21 '13 14:05

jenswirf


People also ask

How do you find the diagonal of a matrix?

Description. D = diag( v ) returns a square diagonal matrix with the elements of vector v on the main diagonal. D = diag( v , k ) places the elements of vector v on the k th diagonal. k=0 represents the main diagonal, k>0 is above the main diagonal, and k<0 is below the main diagonal.

How do you find the diagonal of a matrix in python?

The diag function is numpy. diag(v, k=0) where v is an array that returns a diagonal matrix. Specifying v is important, but you can skip k . If v is an array, it returns a diagonal matrix 4x4 with the array elements as the diagonal matrix elements.


2 Answers

1) The i-th offset reverse diagonal of square matrix m:

off.rev.diag <- function(m, i = 0) m[ (row(m) + col(m) - 1) %% ncol(m) == i ]

For example:

> m <- matrix(1:25, 5); m
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25
> off.rev.diag(m, 1)
[1]  1 10 14 18 22
> off.rev.diag(m, 2)
[1]  2  6 15 19 23

2) We can also write a replacement function:

"off.rev.diag<-" <- function(m, i = 0, value) { 
    m.ix <- matrix(seq_along(m), nrow(m))
    replace(m, off.rev.diag(m.ix, i), value)
}

For example,

> off.rev.diag(m, 1) <- -(1:5)
> m
     [,1] [,2] [,3] [,4] [,5]
[1,]   -1    6   11   16   21
[2,]    2    7   12   17   -5
[3,]    3    8   13   -4   23
[4,]    4    9   -3   19   24
[5,]    5   -2   15   20   25
like image 111
G. Grothendieck Avatar answered Oct 14 '22 12:10

G. Grothendieck


You can do it manually, with some indexing-by-a-vector tricks:

offset.rev.diag <- function(x, nrow, ncol, offset=1) {
    diag(x, nrow, ncol)[rev(1:nrow), c((offset+1):ncol, 1:offset)]
}

> offset.rev.diag(1, 5, 5)
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    0    1    0
[2,]    0    0    1    0    0
[3,]    0    1    0    0    0
[4,]    1    0    0    0    0
[5,]    0    0    0    0    1

> offset.rev.diag(1, 5, 5, 3)
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    1    0    0    0
[2,]    1    0    0    0    0
[3,]    0    0    0    0    1
[4,]    0    0    0    1    0
[5,]    0    0    1    0    0
like image 26
huon Avatar answered Oct 14 '22 10:10

huon