#r #matrix
#r #матрица
Вопрос:
Например, у меня есть матрица 2 * 3
[,1] [,2] [,3]
[1,] 2 4 6
[2,] 3 5 7
Я хочу иметь матрицу 3 * 3, вставляющую 1 по диагонали в R
Вывод :
[,1] [,2] [,3]
[1,] 1 4 6
[2,] 2 1 7
[3,] 3 5 1
Ответ №1:
Одним из вариантов может быть:
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))
Ответ №2:
Используя 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)
Ответ №3:
В случае вашей матрицы вы могли бы поиграть с верхней и нижней матрицами. Я включаю код, который может быть полезен:
#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)))
и избежать назначения единиц в конце.2. @RuiBarradas Большое спасибо за ваш комментарий. Это отличное предложение. Я добавил в конце, чтобы код мог быть более усвояемым для OP.
Ответ №4:
Я просто сравниваю функции, приведенные в предыдущих ответах:
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
функции довольно плохи по производительности.
Комментарии:
1. Было бы интересно посмотреть, как различные параметры ведут себя на больших наборах данных.
Ответ №5:
Вот еще один базовый параметр R, использующий 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
)
что дает
[,1] [,2] [,3]
[1,] 1 4 6
[2,] 2 1 7
[3,] 3 5 1