Вот вариант с использованием lower.tri
и t
транспонировать результат:
k <- 1:15
m <- matrix(0, 5,5)
m[lower.tri(m, diag = TRUE)] <- k
m <- t(m)
m
# [,1] [,2] [,3] [,4] [,5]
#[1,] 1 2 3 4 5
#[2,] 0 6 7 8 9
#[3,] 0 0 10 11 12
#[4,] 0 0 0 13 14
#[5,] 0 0 0 0 15
Microbenchmark
Поскольку существует некоторая путаница с эталоном Иосифа, вот еще один. Я проверил три решения для матриц размером 10 * 10; 100 * 100; 1000 * 1000; 10000 * 10000.
Результаты:
Очевидно, что производительность сильно зависит от размера матрицы. Для больших матриц ответ Джозефа работает быстрее, а для меньших матриц мой - самый быстрый подход. Обратите внимание, что это не учитывает эффективность памяти.
Возпроизводимо тест:
Joseph <- function(k, n) {
y <- 1L
t <- rep(0L,n)
j <- c(y, sapply(1:(n-1L), function(x) y <<- y+(n+1L)-x))
t(vapply(1:n, function(x) c(rep(0L,x-1L),k[j[x]:(j[x]+n-x)]), t, USE.NAMES = FALSE))
}
Frank <- function(k, n) {
m = matrix(0L, n, n)
m[ which(lower.tri(m, diag=TRUE), arr.ind=TRUE)[, 2:1] ] = k
m
}
docendo <- function(k,n) {
m <- matrix(0L, n, n)
m[lower.tri(m, diag = TRUE)] <- k
t(m)
}
library(microbenchmark)
library(data.table)
library(ggplot2)
n <- c(10L, 100L, 1000L, 10000L)
k <- lapply(n, function(x) seq.int((x^2 + x)/2))
b <- lapply(seq_along(n), function(i) {
bm <- microbenchmark(Joseph(k[[i]], n[i]), Frank(k[[i]], n[i]), docendo(k[[i]], n[i]), times = 10L)
bm$n <- n[i]
bm
})
b1 <- rbindlist(b)
ggplot(b1, aes(expr, time)) +
geom_violin() +
facet_wrap(~ n, scales = "free_y") +
ggtitle("Benchmark for n = c(10L, 100L, 1000L, 10000L)")
Проверить равенство результатов:
all.equal(Joseph(k[[1]], n[1]), Frank(k[[1]], n[1]))
#[1] TRUE
all.equal(Joseph(k[[1]], n[1]), docendo(k[[1]], n[1]))
#[1] TRUE
Примечание: я не включал подход Джорджа в сравнении, так как, судя по результатам Иосифа , это, кажется, намного медленнее. Таким образом, все подходы, сравниваемые в моем тесте, написаны только в базе R.
Примечание: '(n^2 - n)/2 + n' равно' sum (seq (n)) '. Хороший ответ! –