在R中添加条件的向量元素

时间:2016-07-15 04:43:45

标签: r performance sum conditional-statements add

假设我有一个我要添加的元素向量:

a <- c(1,2,-7,5)

以下是一些其他测试用例:

a <- c(1,2,-3,5)
a <- c(1,2,-7,-3,5)

我知道我可以使用sum(a)来获得结果,但是如果我有条件要注意的话会怎么样:

current_sum = 0
for(i in 1:length(a)){    
 last_sum = current_sum
 current_sum = current_sum + a[i]
 if(current_sum < 0)
 {
  current_sum = last_sum
  current_sum = current_sum + (a[i]*-1)
 }
}

这里,每次总和为负数时,我们返回前一个总和并添加与该数字相反的数字的相反值。作为第一个例子的结果输出15

显然,元素向量在手之前是未知的,性能是有问题的。是否有任何完全向量化的方法或更有效的方法来执行此操作(避免循环)?

3 个答案:

答案 0 :(得分:5)

我发现R / C接口对于性能很重要的任务非常有用,没有明显的矢量化R解决方案,C中的代码很容易编写。试试这个:

require(inline)
.internalSumPositive<-cfunction(sig=c(v="SEXP"),body="
   double sum=0.0;
   int i,n = length(v);
   double *values = REAL(v);
   SEXP ret = PROTECT(allocVector(REALSXP,1));
   for (i=0;i<n;i++) {
      sum += values[i];
      if (sum<0) sum = sum - 2*values[i];
   }
   REAL(ret)[0] = sum;
   UNPROTECT(1);
   return ret;")

sumPositive<-function(v) {
   if (!is.numeric(v)) stop("Argument must be numeric")
   if (length(v)==0) return(numeric(0))
   .internalSumPositive(as.numeric(v))
}

然后你可以尝试:

sumPositive(c(1,2,-7,5))
#[1] 15
sumPositive(c(1,2,-3,5))
#[1] 5
sumPositive(c(1,2,-7,-3,5))
#[1] 12

我不会报告基准,因为它甚至不是与其他提议的R解决方案的竞争(这可能数万倍)。

答案 1 :(得分:4)

试试这个

f1 <- function(x) repeat{pos<-min(which(cumsum(x)<0))
                    x[pos]<-abs(x[pos])
                    if(all(cumsum(x)>=0)){return(sum(x));break}}
a <- c(1,2,-7,-3,5)
f1(a)
#[1] 12

答案 2 :(得分:4)

尝试Reduce,它可以使用二进制函数折叠向量:

a <- c(1,2,-7,5)
Reduce(function(x, y){x + ifelse(x + y < 0, -y, y)}, a)
## [1] 15

a <- c(1,2,-3,5)
Reduce(function(x, y){x + ifelse(x + y < 0, -y, y)}, a)
## [1] 5

a <- c(1,2,-7,-3,5)
Reduce(function(x, y){x + ifelse(x + y < 0, -y, y)}, a)
## [1] 12