How to replace non-diagonal elements in a matrix?

天涯浪子 提交于 2019-12-02 21:40:47

问题


More specifically, I want all elements other than the diagonal ones (X_11, X_22, X_33,...,X_jj) to be zero.

E.g. I want:

 [1 4 5
  2 3 5
  3 9 8]

to be:

 [1 0 0
  0 3 0
  0 0 8]

Is this possible? Sorry I'm a complete noob at this..


回答1:


The simplest way to do this, is to create a new matrix filled with 0s, then replace its diagonal with the diagonal of the old matrix.

So if you have:

m <- cbind(c(1,2,3), c(4,3,9), c(5, 5, 8))  # The original matrix

diagonal <- diag(m)
m <- matrix(0, nrow(m), ncol(m))  # Overwrite the old matrix
diag(m) <- diagonal



回答2:


It's a simple one liner. First, get the data in:

> (a <- matrix(scan(),nr=3,byrow=TRUE))
1: 1 4 5 2 3 5 3 9 8
10: 
Read 9 items
     [,1] [,2] [,3]
[1,]    1    4    5
[2,]    2    3    5
[3,]    3    9    8

Method 1:

> diag(diag(a))
     [,1] [,2] [,3]
[1,]    1    0    0
[2,]    0    3    0
[3,]    0    0    8

The thing is, if its argument is a matrix, diag extracts the diagonal... but if the argument is a vector, it's a function that creates a diagonal matrix. So just use it twice. (In fact diag has four different uses, depending on what you give it, though two of the cases are quite similar.) See ?diag

If your matrices are huge this isn't likely to be the most efficient way, but for moderate size cases that's the way I do it.

---

Method 2:

A completely different one-liner that also works -

ifelse(row(a)==col(a),a,0)

The two work the same on square matrices. But they have a different result on non-square matrices - the first one returns a square matrix (of dimension the smaller of the two original dimensions), while the second one returns an object of the same shape as its argument; this can be useful depending on the situation.




回答3:


For a matrix of n x m

for i to n
    for j to m
        if i != j
            matrix[i][j] = 0;



回答4:


If m is your matrix try:

m = matrix(c(1,4,5,2,3,5,3,9,8),3,3)
m[upper.tri(m) | lower.tri(m)] = 0

m

##      [,1] [,2] [,3]
## [1,]    1    0    0
## [2,]    0    3    0
## [3,]    0    0    8



回答5:


It simply dependes on the size of the matrix you're dealing with, let's say you have a nxn matrix then the diagonals are gonna be at these places 0, n+1 , 2(n+1), 3(n+1),... if your matrix as you mentioned is not multi dimensional and is linear! so by simply writing a for loop it is possible.




回答6:


I'm transferring my answer from your second post on this topic.

You can use the following to compute a logical matrix which describes the non-diagonal entries of a n×n matrix:

outer(1:n, 1:n, function(i,j) i!=j)

Applied to your example:

> m <- matrix(c(1,2,3,4,3,9,5,5,8),ncol=3)
> m
     [,1] [,2] [,3]
[1,]    1    4    5
[2,]    2    3    5
[3,]    3    9    8
> m[outer(1:3, 1:3, function(i,j) i!=j)] <- 0
> m
     [,1] [,2] [,3]
[1,]    1    0    0
[2,]    0    3    0
[3,]    0    0    8

I also like the triangle approach by @e4e5f4. That might be a bit faster than this code here, but this code here might be easier to adapt to different situations. So it's good to know this one, even if that one might be preferrable for your current application.



来源:https://stackoverflow.com/questions/16705468/how-to-replace-non-diagonal-elements-in-a-matrix

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