我正在嘗試做一個更有效的 for 回圈。我知道 sapply、laaply 等的存在,但我不知道如何在我的代碼中實作它。
我有我的功能,我不知道它是否非常有效。我認為我應該改進這一點,但我不知道如何。
myfun <- function(a, b, c) {
sum <- 0
iter <- 0
while (sum < c) {
nr <- runif(1, a, b)
sum <- sum nr
iter <- iter 1
}
return(iter)
}
這是我想使用樹膠或類似物的部分。
a <- 0
b <- 1
c <- 2
x <- 0
for (i in 1:10^9) {
x <- x myfun(a, b, c)
}
另外,我需要制作一個與此類似的 sapply
sapply(1:10^9, functie(a ,b ,c))
但是 sapply 使用 1:10^9 作為引數,而不是 a、b、c。
uj5u.com熱心網友回復:
我認為replicate()這就是您可能正在尋找的(我將您的內容更改n為較小的)。
set.seed(1234)
n <- 10^2
y <- replicate(n, myfun(a,b,c))
sum(y)
# [1] 462
這與您之前的結果相符。
set.seed(1234)
a <-0
b <-1
c <-2
x <-0
for (i in 1:n){
x <- x myfun(a,b,c)
}
x
# [1] 462
uj5u.com熱心網友回復:
遞回
這是一個遞回函式f(),它的作用與myfun().
f <- function(s=0) {
if (s[length(s)] >= 2) {
return(length(s) - 1L)
} else {
f(c(s, s[length(s)] runif(1, 0L, 1L)))
}
}
set.seed(42)
f()
# [1] 3
replicate(8, f())
# [1] 4 5 4 4 3 5 3 5
stopifnot(all.equal({set.seed(42);f()}, {set.seed(42);myfun(0, 1, 2)}))
但是(并且很可能出于這個原因),它只是更酷,而不是更快。
反傾銷
從中學習,我們可以在 中定義while回圈Rcpp。
library(Rcpp)
cppFunction('
double myfun_cpp() {
double s = 0;
int i = 0;
while (s < 2) {
s = s R::runif(0, 1);
i ;
}
return i;
}
')
set.seed(42)
myfun_cpp()
# [1] 3
replicate(8, myfun_cpp())
# [1] 4 5 4 4 3 5 3 5
stopifnot(all.equal({set.seed(42);myfun_cpp()}, {set.seed(42);myfun(0, 1, 2)}))
現在它快如閃電:
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# f 22.244076 22.639439 25.345203 22.927777 24.089196 35.82683 100 c
# myfun_cpp 3.204448 3.260542 3.843632 3.294618 3.347971 13.71213 100 a
# myfun 16.823981 17.125346 20.605663 17.516248 27.385791 28.63267 100 b
set.seed(42); R <- 1e3
microbenchmark::microbenchmark(
f=replicate(R, f()),
myfun_cpp=replicate(R, myfun_cpp()),
myfun=replicate(R, myfun(0, 1, 2)), times=1e2L,
control=list(warmup=1e1L))
uj5u.com熱心網友回復:
我可能會使用purrr::map(). 例如像這樣:
c(1:1e9) %>%
purrr::map_dbl(
~ myfun(a, b, c)
) %>%
sum()
這首先呼叫myfun()與 的長度相同的次數c(1:1e9),并將結果存盤在一個數字向量中,然后sum()用于將結果相加。
我的測驗表明它比使用replicate().
uj5u.com熱心網友回復:
老實說,你做得對。由于您不需要回傳矢量化或多維結果,而是在每次迭代時更新現有物件,因此您建議的 for 回圈綽綽有余。
如果您想查看有關此主題的一些精彩討論,我建議您查看此鏈接:https : //r4ds.had.co.nz/iteration.html
編輯:只是為了解決速度論點
start <- Sys.time()
purrr::map_dbl(1:1000, function(x) y myfun(a, b, c)) %>% sum
end <- Sys.time()
end - start
# Time difference of 0.02593184 secs
start <- Sys.time()
y <- replicate(1000, myfun(a,b,c))
cumsum(y)[1000]
end <- Sys.time()
end - start
# Time difference of 0.01755929 secs
y <- 0
start <- Sys.time()
for(i in 1:1000){
y<- y myfun(a,b,c)
}
end <- Sys.time()
end - start
# Time difference of 0.01459098 secs
uj5u.com熱心網友回復:
這里有一些選項
- 一個基本的R遞回方法
f_TIC <- function(x, y, z) ifelse(z <= 0, 0, f_TIC(x, y, z - runif(1, x, y)) 1)
Rcpp實施f_TIC
library(Rcpp)
cppFunction("
int f_TIC_cpp(double x, double y, double z) {
if (z <= 0) {
return 0;
} else {
return f_TIC_cpp(x, y, z- R::runif(0,1)) 1;
}
}
")
基準測驗
library(Rcpp)
f <- function(s = 0) {
if (s[length(s)] >= 2) {
return(length(s) - 1L)
} else {
f(c(s, s[length(s)] runif(1, 0L, 1L)))
}
}
f_TIC <- function(x, y, z) ifelse(z <= 0, 0, f_TIC(x, y, z - runif(1, x, y)) 1)
cppFunction("
double myfun_cpp() {
double s = 0;
int i = 0;
while (s < 2) {
s = s R::runif(0, 1);
i ;
}
return i;
}
")
cppFunction("
int f_TIC_cpp(double x, double y, double z) {
if (z <= 0) {
return 0;
} else {
return f_TIC_cpp(x, y, z- R::runif(0,1)) 1;
}
}
")
myfun <- function(a, b, c) {
sum <- 0
iter <- 0
while (sum < c) {
nr <- runif(1, a, b)
sum <- sum nr
iter <- iter 1
}
return(iter)
}
set.seed(42)
R <- 1e3
microbenchmark::microbenchmark(
f = replicate(R, f()),
f_TIC = replicate(R, f_TIC(0, 1, 2)),
f_TIC_cpp = replicate(R, f_TIC_cpp(0,1,2)),
myfun_cpp = replicate(R, myfun_cpp()),
myfun = replicate(R, myfun(0, 1, 2)),
times = 1e2L,
control = list(warmup = 1e1L)
)
我們會看到
Unit: milliseconds
expr min lq mean median uq max neval
f 11.9342 12.50330 14.161982 13.02100 14.96575 22.7116 100
f_TIC 20.1925 21.69420 23.678240 22.28255 24.86350 34.1577 100
f_TIC_cpp 2.0293 2.10080 2.639625 2.17505 2.36190 7.9715 100
myfun_cpp 1.7351 1.79415 2.094577 1.83810 2.00495 6.7481 100
myfun 9.1408 9.45240 11.783504 10.32355 14.68815 19.5400 100
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/395992.html
