【问题标题】:Zeroing some entries of matrix parallel to matrix diagonal in R将矩阵的一些条目归零与R中的矩阵对角线平行
【发布时间】:2014-08-05 07:16:15
【问题描述】:

在 R 中,我想将矩阵对角线上方(和下方)几个条目的所有矩阵条目设置为零。下面是 N x N 矩阵的示例,其中 N = 5,我们删除了与矩阵对角线平行的 k=3 行条目:

a1 b1 c1 d1 e1 -->      a1  b1 00 00 00  
b2 a2 b2 c2 d2 -->      b2  a2 b2 00 00  
c3 b3 a3 b3 c3 -->      00  b3 a3 b3 00  
d4 c4 b4 a4 b4 -->      00  00 b4 a4 b4  
e5 d5 c5 b5 a5 -->      00  00 00 b5 a5  

(00 means the same as 0)

对于 k=2 我们有

a1 b1 c1 d1 e1 -->      a1 b1 c1 00 00  
b2 a2 b2 c2 d2 -->      b2 a2 b2 c2 00  
c3 b3 a3 b3 c3 -->      c3 b3 a3 b3 c3  
d4 c4 b4 a4 b4 -->      00 c4 b4 a4 b4  
e5 d5 c5 b5 a5 -->      00 00 c5 b5 a5  

我已经编写了基于两个连续 for() 循环的简单函数,但是如果我处理大量小矩阵,这个函数太慢了,所有矩阵都是 N x N,N 在 400:450 范围内,k 是总是在 350:370 的范围内,所有矩阵条目都在 -1 和 1 之间(我处理相关矩阵),数据量是几 GB,所以我需要一些矢量化版本的函数。将条目设置为零或将选择的条目复制到新矩阵是否更快?

【问题讨论】:

  • 你的答案在这里:stackoverflow.com/a/13049778/602276
  • @Thomas 这不是完全重复的,所以我没有标记它。这个答案非常有帮助,我以此为灵感发布了这个问题的答案。
  • @Thomas 我编辑了我的问题,添加了 N=5 和 k=3 的情况,请查看参数 k 的作用,如果可以请取消您对关闭此问题的投票
  • @Andrie 是的,我想也许你不会回答,当你给你 +1 时。关闭投票被撤回。

标签: r matrix


【解决方案1】:
set.seed(42)
d <- matrix(rnorm(25), nrow=5)


zero.them<-function(x, n){
  x2<-x
  diag(x)<-0
  for(i in 1:n){
    diag(x[,(-1:-i)])<-0
    diag(x[(-1:-i),])<-0
    }
  x2[which(x==x2)] <- 0
  return(x2)
}

zero.them(d, 1) # for 1 above and below the diagonal

           [,1]        [,2]       [,3]      [,4]     [,5]
[1,]  1.3709584 -0.10612452  0.0000000  0.000000 0.000000
[2,] -0.5646982  1.51152200  2.2866454  0.000000 0.000000
[3,]  0.0000000 -0.09465904 -1.3888607 -2.656455 0.000000
[4,]  0.0000000  0.00000000 -0.2787888 -2.440467 1.214675
[5,]  0.0000000  0.00000000  0.0000000  1.320113 1.895193

zero.them(d, 2) # for 2 above and below the diagonal

           [,1]        [,2]       [,3]       [,4]       [,5]
[1,]  1.3709584 -0.10612452  1.3048697  0.0000000  0.0000000
[2,] -0.5646982  1.51152200  2.2866454 -0.2842529  0.0000000
[3,]  0.3631284 -0.09465904 -1.3888607 -2.6564554 -0.1719174
[4,]  0.0000000  2.01842371 -0.2787888 -2.4404669  1.2146747
[5,]  0.0000000  0.00000000 -0.1333213  1.3201133  1.8951935

【讨论】:

  • 您的函数的行为是正确的,但是否可以用其他解决方案替换 for() 循环?
【解决方案2】:

基于https://stackoverflow.com/a/13049778/602276的答案

试试这个:

mat <- matrix(rnorm(25), nrow=5)

offDiagonal <- function(x, offset=1, diagonal=TRUE){
  off <- (row(x) == (col(x) - offset) | row(x) == (col(x) + offset))  
  if(diagonal) diag(off) <- TRUE
  off
}


mat[!offDiagonal(mat)] <- 0
mat

          [,1]       [,2]       [,3]       [,4]        [,5]
[1,] -2.788105 -0.8399604  0.0000000  0.0000000  0.00000000
[2,]  1.194179 -0.6940815  0.3340976  0.0000000  0.00000000
[3,]  0.000000  0.2256085  0.8885540 -0.3661173  0.00000000
[4,]  0.000000  0.0000000 -1.8024987 -0.1903742 -0.65395419
[5,]  0.000000  0.0000000  0.0000000 -0.4074090  0.08818081

使用offset 参数指定更宽的非对角带:

mat <- matrix(rnorm(25), nrow=5)
mat[!offDiagonal(mat, offset=2)] <- 0
mat

          [,1]       [,2]       [,3]      [,4]       [,5]
[1,] 0.4433126  0.0000000  1.0448629 0.0000000  0.0000000
[2,] 0.0000000 -0.2439675  0.0000000 0.1703401  0.0000000
[3,] 0.2859253  0.0000000 -0.7731495 0.0000000 -0.1722833
[4,] 0.0000000  1.1120145  0.0000000 1.0412452  0.0000000
[5,] 0.0000000  0.0000000  1.0860853 0.0000000 -0.3957575

【讨论】:

  • 但是我的问题中的参数 k 呢,因为你的实现 k 总是 N-2
  • 我使用参数offset 来做到这一点。尝试设置offset=2offset=3
  • 我通过添加 N=5 和 k=2 的大小写来编辑我的问题
  • @Qbik 正如我所说,使用offset 参数。我添加了另一个示例,但功能保持不变。
  • @Andrie 请查看 Frank 解决方案,输出正确,但仍包含 for() 循环
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
  • 2012-12-27
  • 2019-03-10
  • 2019-01-04
相关资源
最近更新 更多