这里有一种使用lower.tri
和t
转置结果的选项:
k <- 1:15
m <- matrix(0, 5,5)
m[lower.tri(m, diag = TRUE)] <- k
m <- t(m)
m
微基准测试
由于Joseph的基准测试存在一些混淆,这里提供另一个测试。我对大小为10*10、100*100、1000*1000、10000*10000的矩阵进行了测试。
结果:
显然,性能严重依赖于矩阵的大小。对于大矩阵,Joseph的方法表现最快,而对于小矩阵,我的方法是最快的。请注意,这并未考虑内存效率。
可复制的基准测试:
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]))
all.equal(Joseph(k[[1]], n[1]), docendo(k[[1]], n[1]))
注意:由于Joseph的结果显示,乔治的方法似乎要慢得多,因此我没有将其方法包括在比较中。因此,在我的基准测试中,所有比较的方法都仅使用基本R编写。
k1,k2等
)。基本R总是让我感到惊奇。 - Joseph Wood