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..
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.
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.
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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With