Давайте использовать Reduce
(нет требований к внешней библиотеке, как правило, хорошая производительность).Я немного изменю функцию, чтобы принять второй (игнорируемый) аргумент:
f1 <- function(x, ign) x^2 + x^3
Reduce(f1, 1:3, init = a)
# [1] 1.872000e+03 6.563711e+09 1.102629e+14
Вот что происходит.Reduce
:
использует двоичную функцию для последовательного объединения элементов данного вектора и, возможно, заданного начального значения.
Первый аргумент - это функция, которую нужно использоватьи он должен принять два аргумента.Первым является значение из предыдущего выполнения функции в этом сокращении.При первом вызове функции используется предоставленное значение init=
.
Первый вызов:
f1(c(1,2,3), 1)
# [1] 2 12 36
Второй вызов:
f1(c(2,12,36), 2)
# [1] 12 1872 47952
Третий вызов:
f1(c(12,1872,47952), 3)
# [1] 1.872000e+03 6.563711e+09 1.102629e+14
Второй аргумент 1:3
используется только для его длины.Все, что имеет правильную длину, будет работать.
Если вы не хотите переопределять f1
только для этого сокращения, вы всегда можете выполнить
Reduce(function(a,ign) f1(a), ...)
Тест:
library(microbenchmark)
r <- Reduce(function(a,b) call("f1", a), 1:3, init=quote(a))
triple_f1 <- function(a) f1(f1(f1(a)))
microbenchmark::microbenchmark(
base = Reduce(function(a,ign) f1(a), 1:3, a),
accum = a %>% accumulate(~ .x %>% f1, .init = f1(a)) %>% extract2(3),
reduc = purrr::reduce(1:3, function(a,ign) f1(a), .init=a),
whil = {
i <- 1
a <- c(1,2,3)
while (i < 10) {
i <- i + 1
a <- f1(a)
}
},
forloop = {
out <- a
for(i in seq_len(3)) out <- f1(out)
},
evaluated = {
r <- Reduce(function(a,b) call("f1", a), 1:3, init=quote(a))
eval(r)
},
precompiled = eval(r),
anotherfun = triple_f1(a)
)
# Unit: microseconds
# expr min lq mean median uq max neval
# base 5.101 7.3015 18.28691 9.3010 10.8510 848.302 100
# accum 294.201 328.4015 381.21204 356.1520 402.6510 823.602 100
# reduc 27.000 38.1005 57.55694 45.2510 54.2005 747.401 100
# whil 1717.300 1814.3510 1949.03100 1861.8510 1948.9510 2931.001 100
# forloop 1110.001 1167.1010 1369.87696 1205.5010 1292.6500 9935.501 100
# evaluated 6.702 10.2505 22.18598 13.3015 15.5510 715.301 100
# precompiled 2.300 3.2005 4.69090 4.0005 4.5010 26.800 100
# anotherfun 1.400 2.0515 12.85201 2.5010 3.3505 1017.801 100