Есть более простой способ сделать то, что вам нужно.Вы можете начать с создания matrix
из length(x) + 1
столбцов и строк со всеми элементами в виде логического TRUE
.Затем сделайте диагональ FALSE
, используя diag()
.Теперь вы можете заменить TRUE
s на нужный вам вектор.На диагональ FALSE
это не влияет.Так как значения заменяются по столбцам, вам нужна заключительная транспонирование t()
для получения правильного результата.
Таким образом, вам не нужно беспокоиться об отслеживании индексов.
x <- c(1,3,5,7,9)
make_matrix <- function(x) {
m <- matrix(TRUE, ncol = length(x) + 1, nrow = length(x) + 1)
diag(m) <- FALSE
m[m] <- x
t(m)
}
make_matrix(x)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 0 1 3 5 7 9
[2,] 1 0 3 5 7 9
[3,] 1 3 0 5 7 9
[4,] 1 3 5 0 7 9
[5,] 1 3 5 7 0 9
[6,] 1 3 5 7 9 0
Вот еще один способ с sapply
.Это создает необходимые элементы строки в каждой итерации и помещает их в матрицу за столбцом.Опять же, вам нужно t()
, чтобы получить правильные результаты.-
sapply(0:length(x), function(a) append(x, 0, after = a)) %>% t()
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 0 1 3 5 7 9
[2,] 1 0 3 5 7 9
[3,] 1 3 0 5 7 9
[4,] 1 3 5 0 7 9
[5,] 1 3 5 7 0 9
[6,] 1 3 5 7 9 0
Тесты -
sapply
медленнее, вероятно, потому что он создает матричные элементы по одной строке за раз и вызывает append
для каждой строки,Все эти издержки избегаются при make_matrix()
подходе.
x <- sample(100)
microbenchmark(
make_matrix = make_matrix(x),
sapply = t(sapply(0:length(x), function(a) append(x, 0, after = a))),
akrun_forloop = {
n <- length(x) + 1
m1 <- matrix(0, n, n)
for(i in seq_len(nrow(m1))) m1[i, -i] <- x
},
times = 1000
)
Unit: microseconds
expr min lq mean median uq max neval
make_matrix 111.495 117.5610 128.3135 126.890 135.7540 225.323 1000
sapply 520.620 551.1765 592.2642 573.335 602.2585 10477.221 1000
akrun_forloop 3380.292 3526.3080 3837.1570 3648.765 3812.5075 20943.245 1000