Looping through diagonal+1 of a matrix

╄→尐↘猪︶ㄣ 提交于 2020-01-23 01:43:25

问题


I need to loop through the diagonal+1 (i.e. the values 1 column to the right of the diagonal) and write the value to a column in a dataframe:

write.csv(data.frame(matrix[1,2], matrix[2,3], matrix[3,4])

How can I do this using a function, rather than just listing all the positions of the values?


回答1:


You can index using a matrix.

eg

m <- matrix(1:25, ncol = 5)

The off diagonals can be accessed using

offd <- cbind(1:4,2:5)


m[offd]

## [1]  6 12 18 24

You could create a function that does this

offdiag <- function(m, offset){
  i <- seq_len(nrow(m)-offset)
  j <- i + offset
  m[cbind(i,j)]

}


offdiag(m, 1)
## [1]  6 12 18 24
offdiag(m, 2)
[1] 11 17 23
offdiag(m, 3)
## [1] 16 22
offdiag(m, 4)
## [1] 21



回答2:


A fast way of doing this without the head-scratching of working out the indices programatically is to use the oft-overlooked row() and col() functions. These return for each element of a matrix the row or column that element belongs to respectively.

The diagonal is where the row index of an element equals the column index. The first subdiagonal is where the row index equals the column index plus 1 whilst the first superdiagonal is where the row index equals the column index minus 1.

Here are some examples:

m <- matrix(1:25, ncol = 5)
m

> 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

The diagonal

m[row(m) == col(m)]
diag(m)

> m[row(m) == col(m)]
[1]  1  7 13 19 25
> diag(m) ## just to show this is correct
[1]  1  7 13 19 25

First subdiagonal

m[row(m) == col(m) + 1

> m[row(m) == col(m) + 1]
[1]  2  8 14 20

First superdiagonal

m[row(m) == col(m) -1]

> m[row(m) == col(m) -1]
[1]  6 12 18 24

Higher-order super- and subdiagonals can be extracted by increasing the value added to the column index.

Creating the data frame and writing out

Essentially you already have this, but

write.csv(data.frame(m[row(m) == col(m) + 1), file = "subdiag.csv")

A general function for sub- or superdiagonals

diags <- function(m, type = c("sub", "super"), offset = 1) {
  type <- match.arg(type)
  FUN <-
  if(isTRUE(all.equal(type, "sub")))
    `+`
  else
    `-`
  m[row(m) == FUN(col(m), offset)] 
}

In use we have:

> diags(m)
[1]  2  8 14 20
> diags(m, type = "super")
[1]  6 12 18 24
> diags(m, offset = 2)
[1]  3  9 15



回答3:


Take the submatrix, then the diagonal of that.

Using mnel's m:

diag(m[, -1])
[1]  6 12 18 24

As a function with variable offset (but in this form, it is not any cleaner than mnel's solution):

offdiag <- function(m, offset) {
  s <- seq(offset)
  diag(m[,-s, drop=FALSE])
}

offdiag(m, 1)
## [1]  6 12 18 24
offdiag(m, 2)
## [1] 11 17 23
offdiag(m, 3)
## [1] 16 22
offdiag(m, 4)
## [1] 21


来源:https://stackoverflow.com/questions/15672585/looping-through-diagonal1-of-a-matrix

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!