For example I have a 2*3 matrix
[,1] [,2] [,3]
[1,] 2 4 6
[2,] 3 5 7
I want to have a 3*3 matrix inserting 1 in the diagonal In R The output :
[,1] [,2] [,3]
[1,] 1 4 6
[2,] 2 1 7
[3,] 3 5 1
For example I have a 2*3 matrix
[,1] [,2] [,3]
[1,] 2 4 6
[2,] 3 5 7
I want to have a 3*3 matrix inserting 1 in the diagonal In R The output :
[,1] [,2] [,3]
[1,] 1 4 6
[2,] 2 1 7
[3,] 3 5 1
One option could be:
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
Or a variation on the original idea (proposed by @Henrik):
mat_new <- diag(ncol(mat))
mat_new[mat_new == 0] <- mat
Sample data:
mat <- structure(2:7, .Dim = 2:3, .Dimnames = list(c("[1,]", "[2,]"),
NULL))
Using 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
Or using replace.
replace(diag(3), diag(3) < 1, m)
# [,1] [,2] [,3]
# [1,] 1 4 6
# [2,] 2 1 7
# [3,] 3 5 1
Data:
m <- structure(2:7, .Dim = 2:3)
In the case of your matrix you could play around upper and lower matrices. I include a code that could be useful:
#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
Now we replace:
#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
The result:
[,1] [,2] [,3]
[1,] 1 4 6
[2,] 2 1 7
[3,] 3 5 1
I just benchmark the functions given from previous answerers:
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)
The result:
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
As we see, the first function is the fastest, followed by the replace method.
As often, the apply functions are quite bad in performance.
Here is another base R option using diag + expand.grid + replace
replace(
diag(ncol(mat)),
as.matrix(subset(do.call(expand.grid, replicate(2, 1:ncol(mat), simplify = FALSE)), Var1 != Var2)),
mat
)
which gives
[,1] [,2] [,3]
[1,] 1 4 6
[2,] 2 1 7
[3,] 3 5 1