提取大矩阵的非对角线切片

13

我有一个大的nxn矩阵,想要取不同大小的对角线切片。例如:

1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5 6

我希望有一个R函数,当给定矩阵和“对角线切片的宽度”时,可以返回一个仅包含这些值的nxn矩阵。因此,对于上面的矩阵和,比如,3,我将得到:

1 x x x x x
1 2 x x x x
1 2 3 x x x
x 2 3 4 x x
x x 3 4 5 x
x x x 4 5 6

目前我正在使用(请原谅)一个非常慢的for循环:

getDiags<-function(ndiags, cormat){
  resmat=matrix(ncol=ncol(cormat),nrow=nrow(cormat))
  dimnames(resmat)<-dimnames(cormat)
  for(j in 1:ndiags){
    resmat[row(resmat) == col(resmat) + j] <- 
      cormat[row(cormat) == col(cormat) + j]
  }
  return(resmat)
}

我意识到这种解决问题的方式不太符合“R”的规范。是否有更好的方法来解决这个问题,可能使用diag或lower.tri?

3个回答

15
size <- 6
mat <- matrix(seq_len(size ^ 2), ncol = size)


low <- 0
high <- 3

delta <- rep(seq_len(ncol(mat)), nrow(mat)) - 
    rep(seq_len(nrow(mat)), each = ncol(mat))
#or Ben Bolker's better alternative
delta <- row(mat) - col(mat)
mat[delta < low | delta > high] <- NA
mat

在我的机器上,这适用于5000 x 5000的矩阵。


这个方法用于我的矩阵中的10个对角线:2.125。我的旧方法(经过的时间):15.170。- 太好了,谢谢! - blmoore
10
你还可以使用 delta <- row(mat)-col(mat);它可能运行起来稍微慢一些,但是非常易于理解阅读。 - Ben Bolker
1
@BenBolker +1,感谢你的解决方案。实际上它比原来快了约30%,并且可以处理更大的矩阵(在我的机器上为8000而不是6000)。 - Thierry

1
如果你想使用 upper.trilower.tri,你可以编写以下类似的函数:
cormat <- mapply(rep, 1:6, 6)

u.diags <- function(X, n) {
  X[n:nrow(X),][lower.tri(X[n:nrow(X),])] <- NA
  return(X)
}

或者

l.diags <- function(X, n) {
  X[,n:ncol(X)][upper.tri(X[,n:ncol(X)])] <- NA
  return(X)
}

或者

n.diags <- function(X, n.u, n.l) {
  X[n.u:nrow(X),][lower.tri(X[n.u:nrow(X),])] <- NA
  X[,n.l:ncol(X)][upper.tri(X[,n.l:ncol(X)])] <- NA
  return(X)
}

l.diags(cormat, 3)
u.diags(cormat, 3)
n.diags(cormat, 3, 1)


0

你可以做:

矩阵:

m<-
matrix(1:6,ncol = 6, nrow=6 ,byrow = T)

函数:

n_diag <- function (x, n) {
    d <- dim(x)
    ndiag <- .row(d) - n >= .col(d)
    x[upper.tri(x) | ndiag] <- NA
    return(x)
}

调用:

n_diag(m,3)

#     [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]    1   NA   NA   NA   NA   NA
#[2,]    1    2   NA   NA   NA   NA
#[3,]    1    2    3   NA   NA   NA
#[4,]   NA    2    3    4   NA   NA
#[5,]   NA   NA    3    4    5   NA
#[6,]   NA   NA   NA    4    5    6

只是为了好玩:

#lapply(1:6, n_diag, x = m)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接