r - 对数据应用函数 n 次 [英] r - apply a function on data n number of times

查看:19
本文介绍了r - 对数据应用函数 n 次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想每次使用函数的输出在向量上应用相同的函数一定次数.

I would like to apply the same function certain number of times on a vector using the output from the function every time.

一个简单的例子,一个简单的功能只是为了演示:

A simplified example with a simple function just to demonstrate:

# sample vector
a <- c(1,2,3)

# function to be applied n times
f1 <- function(x) {
  x^2 + x^3
 }

我想在 an 上应用 f1 的次数,例如这里说 3 次.

I would like to apply f1 on a, n number of times, for example here lets say 3 times.

我听说 purrr::reducepurrr::map() 可能是一个好主意,但无法实现.

I heard purrr::reduce or purrr::map() might be a good idea for this but couldn't make it work.

如果 n = 3 所需的输出将等于 f1(f1(f1(a))).

The desired output if n = 3 would be equal to f1(f1(f1(a))).

推荐答案

我们用Reduce(不需要外部库,一般性能不错).我将稍微修改函数以接受第二个(忽略的)参数:

Let's use Reduce (no external library requirements, generally good performance). I'll modify the function slightly to accept a second (ignored) argument:

f1 <- function(x, ign) x^2 + x^3

Reduce(f1, 1:3, init = a)
# [1] 1.872000e+03 6.563711e+09 1.102629e+14

这就是正在发生的事情.减少:

Here's what's happening. Reduce:

使用二元函数连续组合给定向量的元素和可能给定的初始值.

uses a binary function to successively combine the elements of a given vector and a possibly given initial value.

第一个参数是要使用的函数,它应该接受两个参数.第一个是在此归约中previous 函数执行的值.在第一次调用该函数时,它使用提供的 init= 值.

The first argument is the function to use, and it should accept two arguments. The first is the value from the previous execution of the function in this reduction. On the first call of the function, it uses the init= value provided.

  • 第一次调用:

  • First call:

f1(c(1,2,3), 1)
# [1]  2 12 36

  • 第二次通话:

  • Second call:

    f1(c(2,12,36), 2)
    # [1]    12  1872 47952
    

  • 第三次调用:

  • Third call:

    f1(c(12,1872,47952), 3)
    # [1] 1.872000e+03 6.563711e+09 1.102629e+14
    

  • 第二个参数 1:3 仅用于其长度.任何合适的长度都可以.

    The second argument 1:3 is used just for its length. Anything of the proper length will work.

    如果你不想仅仅为了这个减少而重新定义 f1,你总是可以这样做

    If you don't want to redefine f1 just for this reduction, you can always do

    Reduce(function(a,ign) f1(a), ...)
    

    <小时>

    基准测试:


    Benchmark:

    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
    

    这篇关于r - 对数据应用函数 n 次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆