對于給定的正整數n,我想知道Rcpp用于構造c(1:1, 1:2, ..., 1:n)具有長度的整數向量的最快基 R(非)演算法n*(n 1)/2。快速且記憶體高效的演算法有加分項,因為我最終希望避免分配長度為 的向量n*n。
我知道至少有兩種方法:
unlist(lapply(seq_len(n), seq_len), FALSE, FALSE){J <- .row(c(n, n)); J[upper.tri(J, TRUE)]}
后者效率特別低,因為它分配了兩個長度為 的整數向量n*n。
請注意,如果我們將值分配.col(c(n, n))給J上面,那么我們將獲得序列1 2 2 3 3 3 4 4 4 4 ...。可以使用 快速有效地構建此序列{i <- seq_len(n); rep.int(i, i)}。
我想知道在這種.row(c(n, n))情況下是否存在類似的快速(或更快)演算法,或者unlist-lapply從基本 R 的角度來看是否是最佳的。
FWIW,這是我迄今為止提到的三個程式的基準:
## Seemingly optimal for 1 2 2 3 3 3 4 4 4 4 ...
f0 <- function(n) {i <- seq_len(n); rep.int(i, i)}
## Candidates for 1 1 2 1 2 3 1 2 3 4 ... (the sequence I actually want)
f1 <- function(n) unlist(lapply(seq_len(n), seq_len), FALSE, FALSE)
f2 <- function(n) {J <- .row(c(n, n)); J[upper.tri(J, TRUE)]}
n <- 1000L
microbenchmark::microbenchmark(f0(n), f1(n), f2(n), times = 10000L)
Unit: milliseconds
expr min lq mean median uq max neval
f0(n) 1.711873 1.797891 2.112043 1.810273 1.836636 14.96644 10000
f1(n) 1.986737 2.108630 2.472612 2.148195 2.214369 15.16282 10000
f2(n) 3.785981 4.624821 5.551115 5.051405 5.861954 17.28740 10000
(我知道這f1離f0這里很近,但還有比 更好的f1嗎?)
uj5u.com熱心網友回復:
我不確定你知道什么,但如果函式 frombase沒問題,試試sequence.
f3 <- function(n) {sequence(1:n)}
似乎比它快了將近 2~3 倍 f0
uj5u.com熱心網友回復:
我認為sequence是您所追求的(如果您不打算使用Rcpp更快的版本)
f1 <- function(n) unlist(lapply(seq_len(n), seq_len), FALSE, FALSE)
f2 <- function(n) {
J <- .row(c(n, n))
J[upper.tri(J, TRUE)]
}
f3 <- function(n) {
v <- 1:n
data.table::rowid(rep.int(v, v))
}
f4 <- function(n) sequence(1:n)
n <- 1000L
microbenchmark::microbenchmark(f1(n), f2(n), f3(n), f4(n), check = "identical")
基準測驗
> microbenchmark::microbenchmark(f1(n), f2(n), f3(n), f4(n), check = "identical")
Unit: microseconds
expr min lq mean median uq max neval
f1(n) 3928.8 4144.50 5185.839 4227.5 4289.15 67457.1 100
f2(n) 9490.3 10083.90 14415.777 12951.0 15080.50 78014.2 100
f3(n) 8083.5 8572.10 12154.922 9063.0 9534.45 75408.7 100
f4(n) 213.9 425.05 787.637 442.6 494.00 7844.4 100
uj5u.com熱心網友回復:
這兩個也可能是選項-
n <- 5
unlist(purrr::map(seq(5), ~seq(.x)))
#> [1] 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5
unlist(mapply(FUN = function(.x) seq(.x), seq(n)))
#> [1] 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5
由reprex 包(v2.0.1)于 2021 年 12 月 10 日創建
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/380997.html
上一篇:如何降低成本?
下一篇:如何有效地創建子串
