在r中的某个阈值处中断cumsum()函数

在r中的某个阈值处中断cumsum()函数,r,cumsum,R,Cumsum,例如,我有以下代码: cumsum(1:100) 我想打破它,如果元素I+1大于3000。我该怎么做 因此,不是这个结果: [1] 1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190 210 231 253 276 300 [25] 325 351 378 406 435 465 496 528 561 595 630 6

例如,我有以下代码:

cumsum(1:100)
我想打破它,如果元素I+1大于3000。我该怎么做

因此,不是这个结果:

[1]    1    3    6   10   15   21   28   36   45   55   66   78   91  105  120  136  153  171  190  210  231  253  276  300
 [25]  325  351  378  406  435  465  496  528  561  595  630  666  703  741  780  820  861  903  946  990 1035 1081 1128 1176
 [49] 1225 1275 1326 1378 1431 1485 1540 1596 1653 1711 1770 1830 1891 1953 2016 2080 2145 2211 2278 2346 2415 2485 2556 2628
 [73] 2701 2775 2850 2926 3003 3081 3160 3240 3321 3403 3486 3570 3655 3741 3828 3916 4005 4095 4186 4278 4371 4465 4560 4656
 [97] 4753 4851 4950 5050
我希望得到以下结果:

 [1]    1    3    6   10   15   21   28   36   45   55   66   78   91  105  120  136  153  171  190  210  231  253  276  300
 [25]  325  351  378  406  435  465  496  528  561  595  630  666  703  741  780  820  861  903  946  990 1035 1081 1128 1176
 [49] 1225 1275 1326 1378 1431 1485 1540 1596 1653 1711 1770 1830 1891 1953 2016 2080 2145 2211 2278 2346 2415 2485 2556 2628
 [73] 2701 2775 2850 2926

我们可以使用
,正如我在评论中提到的,在Rcpp中编写一些简单的东西对我这样的人来说也不是什么大不了的事。这是一个非常原始的实现,似乎可以工作(感谢@MatthewLundberg的改进建议)


我不知道R里有什么东西。您可能很容易在Rcpp中编写一些东西。您可以通过将内部测试更改为
if(y&&res[i]>y)
@DavidArenburg来删除外部“if”。感谢您对我的答案(使用base R)的评论。你是对的,我完全测试错了。已删除,以免将其他人引入歧途@西蒙杰克逊不需要删除你的答案。这是完全好的(我们仍然在毫秒世界),我的意思是你需要确保你的基准是正确的。e、 例如,在某些情况下,您的实现会更好,在其他情况下,
cumsum
会赢-但仍然是
,而
循环可能会更高效地使用内存,或者诸如此类。我运行了一些更大的测试,它会变得更慢(def超过ms计时)。Rcpp是更好的方式。你的一个想法是:在
x
上操作而不是创建
res
会加快速度吗?如果没有其他东西,内存效率会更高。@SimonJackson,是的,它会,但它也会在全局环境中修改
x
,我们不希望这样。尝试
cppFunction('NumericVector测试(NumericVector x){NumericVector res=x;for(inti=1;iv1[v1 <=3000]
setdiff(pmin(cumsum(1:100), 3000), 3000)
v1 <- cumsum(1:100)
library(Rcpp)
cppFunction('NumericVector cumsumCPP(NumericVector x, int y = 0){

    // y = 0 is the default
    // Need to do this in order to avoid modifying the original x
    int n = x.size();
    NumericVector res(n);
    res[0] = x[0];

    for (int i = 1 ; i < n ; i++) {
      res[i] = res[i - 1] + x[i];
      if (res[i] > y && (y != 0)) { 
        // This breaks the loop if condition met
        return res[seq(0, i - 1)];
      }
    }

    // This handles cases when y== 0 OR y != 0 and y > cumsum(res)
    return res;
}')

cumsumCPP(1:100, 3000)
#  [1]    1    3    6   10   15   21   28   36   45   55   66   78   91  105  120  136  153  171  190  210  231  253  276  300
# [25]  325  351  378  406  435  465  496  528  561  595  630  666  703  741  780  820  861  903  946  990 1035 1081 1128 1176
# [49] 1225 1275 1326 1378 1431 1485 1540 1596 1653 1711 1770 1830 1891 1953 2016 2080 2145 2211 2278 2346 2415 2485 2556 2628
# [73] 2701 2775 2850 2926
set.seed(123)
x <- as.numeric(sample(1:1e3, 1e7, replace = TRUE))
microbenchmark::microbenchmark(cumsum(x), cumsumCPP(x))
# Unit: milliseconds
#         expr      min        lq      mean   median        uq       max neval cld
#    cumsum(x) 58.61942  61.46836  72.50915  76.7568  80.97435  99.01264   100  a 
# cumsumCPP(x) 98.44499 100.09979 110.45626 112.1552 119.22958 131.97619   100   b

identical(cumsum(x), cumsumCPP(x))
## [1] TRUE