【问题标题】:Cumulative multiplication in R with the addition of extra constantsR中的累积乘法加上额外的常数
【发布时间】:2019-02-07 09:41:07
【问题描述】:

我是 R 新手,正在努力解决以下累积乘法与额外常数相加的组合。我希望在数据框中实现以下目标:

Variable_X         Variable_Y           Variable_Z
X1                 Y1                   Y1*X1      = Z1 
X2                 Y2                   (Z1+Y2)*X2 = Z2 
X3                 Y3                   (Z2+Y3)*X3 = Z3
X4                 Y4                   (Z3+Y4)*X4 = Z4

任何帮助将不胜感激。

【问题讨论】:

  • 亲爱的,我现在已经扩展了分析以包括变量 X (1000+) 的不同值的大量列,对于每个我想计算变量 Z (我基本上做蒙特卡洛)。 Y 是不变的和不变的。这些解决方案中的任何一个都可以适应更大的数据集吗?
  • 那么 Rcpp 解决方案是一个明显的胜利。假设您的数据框是dat,其中x 列由ind 索引。你可以z <- lapply(dat[ind], foo_cpp, dat$y)

标签: r cumulative-sum


【解决方案1】:

仅使用基 R 定义一个匿名函数来体现迭代,然后使用 Reduce 运行它:

transform(DF, Z = Reduce(f = function(prev, i) (prev + Y[i]) * X[i], 
                         x = seq_along(X), init = 0, acc = TRUE)[-1])

给予(用于末尾注释中的输入):

  X   Y    Z
1 1 101  101
2 2 102  406
3 3 203 1827
4 4 104 7724

添加

gsubfn 函数允许函数定义的简短形式,使用它我们可以将上面的内容重写为:

library(gsubfn)

transform(DF, Z = fn$Reduce(f = prev + i ~ (prev + Y[i]) * X[i], 
                         x = seq_along(X), init = 0, acc = TRUE)[-1])

注意

我们使用了以下输入:

DF <- data.frame(X = 1:4, Y = 101:104)

【讨论】:

  • 这里有几个tidyverse 翻译:mutate(DF, Z = accumulate(1:n(), ~(.x + Y[.y]) * X[.y],.init=0)[-1])mutate(DF, Z=X*Y, Z = accumulate(2:n(), ~ Z[.y] +.x * X[.y],.init=Z[1]))purrr 有一个函数 reduce2 可以方便地避免索引的尴尬使用,但由于某种原因没有 accumulate2 。有一个关于它的问题:github.com/tidyverse/purrr/issues/511
  • 我认为accumulate 解决方案的尴尬不是使用索引,而是需要使用.x.y 在位置上引用参数,而不是使用有意义的名称。 gsubfn 包还支持使用公式的函数规范,但它允许程序员选择参数名称。请参阅上面添加的部分。
【解决方案2】:
library(Rcpp)

cppFunction("NumericVector foo_cpp (NumericVector x, NumericVector y) {
  int n = x.size(), i;
  NumericVector z(n);
  double tmp = 0.0;
  for (i = 0; i < n; i++) {
    tmp = (tmp + y[i]) * x[i];
    z[i] = tmp;
    }
  return z;
  }")

set.seed(0)
dat <- data.frame(x = runif(1e+6), y = runif(1e+6))
system.time(z <- foo_cpp(dat$x, dat$y))
#   user  system elapsed 
#  0.016   0.000   0.014 
dat$z <- z

【讨论】:

    【解决方案3】:

    我相信老式的 for 循环是解决此问题的最佳方法。

    dat <- data.frame(Variable_X = 1:10, Variable_Y = 11:20)
    
    dat$Variable_Z <- dat$Variable_X[1]*dat$Variable_Y[1]
    for(i in seq_len(nrow(dat))[-1]){
      dat$Variable_Z[i] <- (dat$Variable_Z[i - 1] + dat$Variable_Y[i])*dat$Variable_X[i]
    }
    
    dat
    #   Variable_X Variable_Y Variable_Z
    #1           1         11         11
    #2           2         12         46
    #3           3         13        177
    #4           4         14        764
    #5           5         15       3895
    #6           6         16      23466
    #7           7         17     164381
    #8           8         18    1315192
    #9           9         19   11836899
    #10         10         20  118369190
    

    【讨论】:

      猜你喜欢
      • 2016-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-12
      • 2018-12-29
      • 2021-11-10
      • 2016-08-06
      • 2013-06-19
      相关资源
      最近更新 更多