Is there any diag()-like way of creating diagonal matrix of unequal dimensions in r? For instance:
> diag(rep(1,9), nrow=3)
1 1 1 0 0 0 0 0 0
0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 1 1 1
Try the Kronecker product
> kronecker(diag(1, 3), t(rep(1, 3)))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 1 1 1 0 0 0 0 0 0
[2,] 0 0 0 1 1 1 0 0 0
[3,] 0 0 0 0 0 0 1 1 1
or shorter and equivalent form with %x%
> diag(1, 3) %x% t(rep(1, 3))
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 1 1 1 0 0 0 0 0 0
[2,] 0 0 0 1 1 1 0 0 0
[3,] 0 0 0 0 0 0 1 1 1
Other options might be using tcrossprod + rep
> n <- 3
> +(tcrossprod(rep(1, n), rep(1:n, each = n)) == 1:n)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 1 1 1 0 0 0 0 0 0
[2,] 0 0 0 1 1 1 0 0 0
[3,] 0 0 0 0 0 0 1 1 1
or outer + ==
> n <- 3
> +outer(1:n, rep(1:n, each = n), `==`)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 1 1 1 0 0 0 0 0 0
[2,] 0 0 0 1 1 1 0 0 0
[3,] 0 0 0 0 0 0 1 1 1
f0 <- function(n) {
diag(1, n) %x% t(rep(1, n))
}
f1 <- function(n) {
+(tcrossprod(rep(1, n), rep(1:n, each = n)) == 1:n)
}
f2 <- function(n) {
+outer(1:n, rep(1:n, each = n), `==`)
}
bm <- function(n) {
microbenchmark(
kron = f0(n),
tprep = f1(n),
outer = f2(n),
check = "equivalent",
unit = "relative"
)
}
shows
> bm(3)
Unit: relative
expr min lq mean median uq max neval
kron 11.895263 11.04810 1.7791532 10.679845 10.037901 0.8851459 100
tprep 1.000000 1.00000 1.0000000 1.000000 1.000000 1.0000000 100
outer 2.421579 2.38119 0.9050314 2.363099 2.249479 0.7652963 100
> bm(10)
Unit: relative
expr min lq mean median uq max neval
kron 5.306864 5.097848 4.241431 4.915007 4.810881 4.291035 100
tprep 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 100
outer 2.076524 2.017677 1.719520 1.966105 1.929139 1.177178 100
> bm(100)
Unit: relative
expr min lq mean median uq max neval
kron 1.194080 1.267156 1.072417 1.318485 1.068942 0.2659374 100
tprep 1.000000 1.000000 1.000000 1.000000 1.000000 1.0000000 100
outer 1.583671 1.582495 1.387049 1.445595 1.288268 1.0790626 100
One more option for generating m by n matrix as described:
m <- 3L
n <- 9L
stopifnot(n>=m, n %% m == 0L)
diag(nrow=m)[, rep(1L:m, each = n %/% m)]
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
# [1,] 1 1 1 0 0 0 0 0 0
# [2,] 0 0 0 1 1 1 0 0 0
# [3,] 0 0 0 0 0 0 1 1 1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With