Replacing non-diagonal elements in a matrix in R (

2019-08-04 06:07发布

问题:

This question already has an answer here:

  • How to replace non-diagonal elements in a matrix? 6 answers

Okay, I asked this question earlier but I got bashed (deservedly) for not specifying anything and showing no sign of previous attempt. So let me try again..

I'm using R, and I have a 463✕463 matrix. What I would like to do is to replace all elements other than the diagonal ones (X11, X22, X33,...,Xjj) with 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]

When I use the diag() function, it simply gives me a column vector of the diagonal values. I imagine I can use the replace() function somehow combined with a "if not diagonal" logic...but I am lost.

And yes, as some here have guessed, I am probably much younger than many people here and am completely new at this...so please put me in the right direction. Really appreciate all your help!

回答1:

In R, the diag method has two functions.

  1. It returns the diagonal of a matrix. I.e.

    m <- matrix(1:9, ncol=3)
    m
    #      [,1] [,2] [,3]
    # [1,]    1    4    7
    # [2,]    2    5    8
    # [3,]    3    6    9
    diag(m)
    # [1] 1 5 9
    
  2. It can construct a diagonal matrix.

    diag(1:3)
    #      [,1] [,2] [,3]
    # [1,]    1    0    0
    # [2,]    0    2    0
    # [3,]    0    0    3
    

So in your case, extract the diagonal from your existing matrix and supply it to diag:

diag(diag(m))
#      [,1] [,2] [,3]
# [1,]    1    0    0
# [2,]    0    5    0
# [3,]    0    0    9


回答2:

using outer

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

using triangles

A possible alternative would be combining the two triangles on either side of the diagonal. In this case, you use the matrix m itself as input to determine the size.

upper.tri(m) | lower.tri(m)

Applied to your use case:

> m[upper.tri(m) | lower.tri(m)] <- 0

It seems you already got this answer in response to your original post…



回答3:

m[ col(m)==row(m) ] <- 0

> m <- matrix(1:9, 3)
> m[ col(m)==row(m) ]
[1] 1 5 9
> m[ col(m)!=row(m) ] <- 0
> m
     [,1] [,2] [,3]
[1,]    1    0    0
[2,]    0    5    0
[3,]    0    0    9


标签: r replace