代码之家  ›  专栏  ›  技术社区  ›  Brani

如何生成序列中的前n项:

  •  2
  • Brani  · 技术社区  · 7 年前

    潮人之路?(假设n=10)

    enter image description here

    我想 lag 会有帮助,但我无法得到正确的结果。

    2 回复  |  直到 7 年前
        1
  •  3
  •   Maurits Evers    7 年前

    这里有一个稍微不同的选择

    f <- function(a1 = 1, n = 10) {
        ret <- numeric(n)   # Pre-allocation
        ret[1] <- a1
        for (i in 2:length(ret)) ret[i] <- 5 * ret[i - 1] + 3 ^ (i - 1)
        ret
    }
    f(n = 10)
    #[1]       1       8      49     272    1441    7448   37969  192032  966721
    #[10] 4853288
    

    1. 我们用 numeric(n) 这比做动作要快。 rep(0, 10) .
    2. 剩下的只是经典 for

    或C++解决方案使用 Rcpp

        library(Rcpp)
        cppFunction("
        IntegerVector f2(int n = 10, int a1 = 1) {
            IntegerVector ret(n, a1);
            for (int i = 1; i < n; i++) {
                ret[i] = 5 * ret[i - 1] + pow(3, i);
            }
            return ret;
        }")
        f2(10)
        # [1]       1       8      49     272    1441    7448   37969  192032  966721
        #[10] 4853288
    

    和一个 microbenchmark 比较

        library(microbenchmark)
        res <- microbenchmark(
            R_for_loop = f(n = 10),
            Rcpp_for_loop = f2(n = 10)
        )
        #Unit: microseconds
        #          expr   min     lq    mean median     uq    max neval cld
        #    R_for_loop 3.226 3.4195 3.78043 3.4945 3.5625 29.365   100   b
        # Rcpp_for_loop 1.913 2.0980 2.36980 2.2560 2.3495 12.582   100  a
    
    
        library(ggplot2)
        autoplot(res)
    

    enter image description here

        2
  •  2
  •   loki    7 年前

    这里有一个经典的for循环方法。因为您需要在之前访问迭代的结果,所以这可能是合适的方法。

    library(dplyr)
    t <- tibble(k = 1:10, a = NA)
    
    for (i in 1:nrow(t)){
      if (i == 1){
        t[i, "a"] <- 1
      } else {
        t[i, "a"] <- 5 * t[i - 1, "a"] + 3 ^ t[i - 1, "k"]
      }
    }
    t
    # A tibble: 10 x 2
    #        k       a
    #    <int>   <dbl>
    # 1      1       1
    # 2      2       8
    # 3      3      49
    # 4      4     272
    # 5      5    1441
    # 6      6    7448
    # 7      7   37969
    # 8      8  192032
    # 9      9  966721
    # 10    10 4853288
    
        3
  •  2
  •   niko    7 年前

    你也可以使用 vapply 为了这个

    # Init
    len <- 10L + 1L
    init = 1L
    x <- numeric(len); x[[1]] <- init
    # Create sequence
    vapply(2:len, function (k) x[[k]] <<- 5*x[[k-1L]] + 3^(k-1L), numeric(1))
    # Result
    x
    # [1]        1        8       49      272     1441     7448    37969   192032   966721  4853288 24325489
    
        4
  •  2
  •   user11113339 user11113339    7 年前

    Tidyverse解决方案:比“for_loop”和“vapply”方法慢

    library(tidyverse)
    
    # f31 is slightly faster (using function) instead of formula (on f32)
    f31 <- function(a1 = 1, n = 10) {
      x <- c(a1,rep(0,n-1))
       map_dbl(2:n, function (k) x[k]  <<-  5*x[k-1] + 3^(k-1))
      return(x)
    } #func 
    
    f31(n=10)
    # [1]       1       8      49     272    1441    7448   37969  192032  966721
    # [10] 4853288
    
    f32 <- function(a1 = 1, n = 10) {
      x <- c(a1,rep(0,n-1))
      map_dbl(2:n, ~ {x[.]  <<-  5*x[.-1] + 3^(.-1)})
      return(x)
    } # func 
    
    f32(n=10)
    # [1]       1       8      49     272    1441    7448   37969  192032  966721
    # [10] 4853288