通过在R中将对角线元素添加为1,从n-1*n矩阵创建n*n矩阵

5
例如,我有一个 2*3 的矩阵。
     [,1] [,2] [,3]
[1,]    2    4    6
[2,]    3    5    7

我想在R中创建一个3*3的矩阵,在对角线上插入1。 输出为:
     [,1] [,2] [,3]
[1,]    1    4    6
[2,]    2    1    7
[3,]    3    5    1
5个回答

6

一个选项可能是:

mat_new <- `diag<-`(matrix(ncol = ncol(mat), nrow = nrow(mat) + 1, 0), 1)
mat_new[mat_new == 0] <- mat

     [,1] [,2] [,3]
[1,]    1    4    6
[2,]    2    1    7
[3,]    3    5    1

或原始想法的变体(由@Henrik提出):

mat_new <- diag(ncol(mat))
mat_new[mat_new == 0] <- mat

样本数据:

mat <- structure(2:7, .Dim = 2:3, .Dimnames = list(c("[1,]", "[2,]"), 
    NULL))

4

使用 append 方法。

unname(mapply(function(x, y) append(x, 1, y), as.data.frame(m), 1:ncol(m) - 1))

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

或者使用replace函数。

replace(diag(3), diag(3) < 1, m)
#      [,1] [,2] [,3]
# [1,]    1    4    6
# [2,]    2    1    7
# [3,]    3    5    1

数据:

m <- structure(2:7, .Dim = 2:3)

2
在您的矩阵中,您可以尝试使用上下三角矩阵。以下是一个可能有用的代码示例:
#Input matrix
A <- matrix(c(2,4,6,3,5,7),nrow = 2,ncol = 3,byrow = T)

     [,1] [,2] [,3]
[1,]    2    4    6
[2,]    3    5    7


#Output matrix
B <- matrix(0,nrow = 3,ncol = 3)

     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    0    0    0
[3,]    0    0    0

现在我们要替换:
#Replace
B[upper.tri(B)] <- A[upper.tri(A)] 
B[lower.tri(B)] <- A[lower.tri(A,diag = T)]
diag(B) <- 1
#Final output
B

结果如下:
     [,1] [,2] [,3]
[1,]    1    4    6
[2,]    2    1    7
[3,]    3    5    1

1
您可以创建 B <- diag(max(nrow(A), ncol(A))),从而避免在最后分配1。 - Rui Barradas
@RuiBarradas 非常感谢您的评论。这是一个很好的建议。我在最后添加了一些内容,以便代码更易于被 OP 理解。 - Duck

0

我刚刚对之前回答者提供的函数进行了基准测试:

add_diagonal <- function(mat) {
  res <- diag(ncol(mat))
  res[res == 0] <- mat
}

add_diagonal_1 <- function(mat) {
  n <- max(dim(mat))
  res <- matrix(0, nrow=n, ncol=n)
  res[upper.tri(res)] <- mat[upper.tri(mat)]
  res[lower.tri(res)] <- mat[lower.tri(mat)]
  diag(res) <- 1
  res
}

add_diagonal_2 <- function(mat) {
  n <- max(dim(mat))
  replace(diag(n), diag(n) < 1, mat)
}

add_diagonal_3 <- function(mat) {
  unname(mapply(function(x, y) append(x, 1, y), as.data.frame(mat), 1:ncol(mat) - 1))
}

require(microbenchmark)

A <- matrix(c(2,4,6,3,5,7),nrow = 2,ncol = 3,byrow = T)

microbenchmark(add_diagonal(A), add_diagonal_1(A), add_diagonal_2(A), add_diagonal_3(A), times=10000)

结果:

Unit: microseconds
              expr     min       lq      mean   median       uq       max neval
   add_diagonal(A)   8.569  10.3865  13.17156  11.8440  14.4760  5256.301 10000
 add_diagonal_1(A)  40.601  44.2130  51.68039  48.7940  51.7795 11519.797 10000
 add_diagonal_2(A)  14.279  16.8790  20.60770  18.8860  21.7520  5966.649 10000
 add_diagonal_3(A) 166.582 173.1480 189.50570 175.8495 179.2100  8586.079 10000
  cld
 a   
   c 
  b  
    d

我们可以看到,第一个函数是最快的,其次是replace方法。

通常情况下,apply函数在性能方面表现不佳。


2
看看在更大的数据集上不同选项的表现会很有趣。 - tmfmnk

0

这里是另一种使用 diag + expand.grid + replace 的基本 R 选项

replace(
  diag(ncol(mat)),
  as.matrix(subset(do.call(expand.grid, replicate(2, 1:ncol(mat), simplify = FALSE)), Var1 != Var2)),
  mat
)

这提供了

     [,1] [,2] [,3]
[1,]    1    4    6
[2,]    2    1    7
[3,]    3    5    1

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