【问题标题】:Cumulative sum with restart, optimization in R重启的累积和,R中的优化
【发布时间】:2019-07-29 22:01:11
【问题描述】:

我有 34 个栅格(nrow:17735,ncol:11328,ncell:200902080),值为 0 和 1,每个 4Mb。我想要这些值的累积和零重置。

我尝试了几种基于:Cumulative sum that resets when 0 is encountered

library(microbenchmark)
library(compiler)
library(dplyr)
library(data.table)

x <- c(0,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0)

fun = function(x)
{ cs = cumsum(x)
  cs - cummax((x == 0) * cs)
}
funC <- cmpfun(fun)

microbenchmark(
funcioEx = fun(x),
funComEx = funC(x),
lapplyEx = unname(unlist(lapply(split(x,cumsum(c(0,diff(x) != 0))), cumsum))),
dataTaEx = data.table(x)[, whatiwant := cumsum(x), by = rleid(x==0L)],
reduceEx = Reduce(function(x, y) if (y == 0) 0 else x+y, x, accumulate=TRUE)
)

我想针对我的数据优化此过程,因为使用第二个选项(funComEx,最快)大约需要 3 个小时。

【问题讨论】:

  • 我认为 fun 可能是 R 中最快的方法之一。查看 Rcpp 包以获得更快的速度可能会有所帮助。

标签: r optimization cumsum microbenchmark


【解决方案1】:

Rcpp 可能会有所帮助

library(Rcpp)
cppFunction(
    "IntegerVector foo(NumericVector vect){
    int N = vect.size();
    IntegerVector ans(N);
    ans[0] = vect[0];
    for (int i = 1; i < N; i++){
      if(vect[i] > 0){
        ans[i] = ans[i-1] + vect[i];
      } else {
        ans[i] = 0;
      }
    }
    return(ans);
  }"
)

set.seed(42)
x = sample(0:1, 1e4, TRUE)

identical(foo(x), fun(x))
#[1] TRUE

microbenchmark(
    funcioEx = fun(x),
    funComEx = funC(x),
    lapplyEx = unname(unlist(lapply(split(x,cumsum(c(0,diff(x) != 0))), cumsum))),
    dataTaEx = data.table(x)[, whatiwant := cumsum(x), by = rleid(x==0L)],
    reduceEx = Reduce(function(x, y) if (y == 0) 0 else x+y, x, accumulate=TRUE),
    foo_RCPP = foo(x)
)
#Unit: microseconds
#     expr       min         lq        mean     median         uq       max neval
# funcioEx    98.238   104.2495   118.81500   113.1935   121.1110   280.637   100
# funComEx    97.358   103.2230   113.81515   112.1670   118.1785   220.522   100
# lapplyEx 17810.638 18888.9055 20130.20765 19399.7415 20641.0550 28073.981   100
# dataTaEx  3435.387  3832.0025  4468.77932  4023.6395  4347.3840 17053.181   100
# reduceEx  7472.515  8174.4020  9614.23122  8634.7985 10177.1305 15719.788   100
# foo_RCPP    52.491    62.6085    80.65777    66.5670    72.4320  1102.315   100

【讨论】:

  • 谢谢。 Rcpp 选项不起作用。我从这里cran.r-project.org/bin/windows/Rtools 安装了Rtools,我收到以下错误:警告消息:在系统(cmd)中:找不到'make' sourceCpp中的错误(code = code,env = env,rebuild =rebuild,cacheDir = cacheDir,:构建共享库时出现错误 1。警告:未找到为 R 构建 C++ 代码所需的工具。请下载并安装适当版本的 Rtools:cran.r-project.org/bin/windows/Rtools
  • 我能够安装 Rtools 并运行脚本。显着提高速度。但是,当我将它应用于栅格堆栈 (rasterStack) 时,出现以下错误:Error in foo (rasterStack): Not compatible with requested type: [type = S4; target = double]. 我认为这是因为在示例中我使用了矢量,但我不知道如何在脚本中适应栅格.我很感激任何建议。
  • 这是一个带有数组和相应错误的示例:library(raster) # Sample data r1 &lt;- r2 &lt;- r3 &lt;- raster(matrix(0, 10, 10)) r &lt;- stack(r1, r2, r3) one &lt;- c(15:20, 25:30, 35:40, 45:50, 55:60) r[one] &lt;- 1 library(Rcpp) cppFunction( "IntegerVector foo(NumericVector vect){ int N = vect.size(); IntegerVector ans(N); ans[0] = vect[0]; for (int i = 1; i &lt; N; i++){ if(vect[i] &gt; 0){ ans[i] = ans[i-1] + vect[i]; } else { ans[i] = 0; } } return(ans); }" ) foo(r)
  • 此脚本适用于“Rasterbrick”对象,但不适用于“RasterStack”,我在 RasterStack 中有栅格。我试过这个来重现错误:rStack &lt;- stack(r); rFooStack = rStack ; rFooStack@layers@values[] = t(apply(rStack@layers@values, 1, foo)) Error in apply(rStack@layers@values, 1, foo): trying to get slot "values" from an object of a basic class ("list") with no slots. 这是我在 RasterStack 中应用它时给我的错误。再次感谢。
  • 最后,我可以使用我的数据运行脚本。现在错误是:Error: cannot allocate vector of size 25.4 Gb。我使用了 rasterStack 的object.size(),结果是440224 bytes。还有其他建议吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
  • 2021-06-13
  • 2013-05-20
  • 2020-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多