Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这个R函数可以矢量化吗? bucketinex_R_Vectorization_Conditional Statements - Fatal编程技术网

这个R函数可以矢量化吗? bucketinex

这个R函数可以矢量化吗? bucketinex,r,vectorization,conditional-statements,R,Vectorization,Conditional Statements,这里有一个尝试(尚未到达bucketinex!): 你的 bucketIndex <- function(v, N){ o <- rep(0, length(v)) curSum <- 0 index <- 1 for(i in seq(length(v))){ o[i] <- index curSum <- curSum + v[i] if(curSum > N){ curSum <-

这里有一个尝试(尚未到达
bucketinex
!):

  • 你的

    bucketIndex <- function(v, N){
      o <- rep(0, length(v))
    
      curSum <- 0
      index  <- 1
    
      for(i in seq(length(v))){
        o[i] <- index
    
        curSum <- curSum + v[i]
        if(curSum > N){
          curSum <- 0
          index <- index + 1
        }
      }
    
      o
    }
    
    > bucketIndex(c(1, 1, 2, 1, 5, 1), 3)
    [1] 1 1 1 2 2 3
    
    也就是说,只需在
    v
    中交换两个连续条目,结果中的最大值就会不同

  • 另一点是,仅在导致总和为>
    N
    的元素之后进行计数。这意味着结果的开头应该有一个额外的1,最后一个元素应该被删除

  • 您可以将
    curSum
    重置为0,而不管它在
    N
    上射出多少。因此,对于所有具有
    cumsum(v)>N
    的元素,您需要减去该值,然后查找下一个
    cumsum(v)>N
    ,依此类推。这就减少了与
    for
    循环相关的循环迭代次数,但这是否会给您带来本质上的改进取决于
    v
    的条目和
    N
    (或者,取决于
    max(index)
    长度(v)
    比率)。如果这是你例子中的50%,我认为你不能获得实质性的收益。除非它们之间至少有一个magnitute顺序,否则我会选择
    inline::cfunction


我要冒险说,答案是“不”。本质上,你是在根据当前总和的结果改变你的总和。这意味着未来的计算取决于中间计算的结果,而矢量化操作无法做到这一点

我不认为这是完全可以矢量化的,但是@cbeleites通过一次处理整个块(bucket)来减少循环中的迭代次数。每次迭代查找累计和超过
N
的位置,将索引分配给该范围,将累计和减少超过
N
的任何值,并重复,直到向量用尽。其余的是记账(初始化值和增加值)


bucketIndex2
cumsum
是否为您处理此问题<代码>光标]不,那是另一个函数。。sum()只返回一个长度为1的向量。你能评论一下它应该做什么吗?它接近于累积和的整数除法(
cumsum(v)%/%N
),但复杂的部分是
curSum
被设置回0(而不是模
cumsum(v)%%N
。请参见我第一次尝试的答案。我想对v的连续元素进行分组,以便每个组中的和都大于N(可能最后一组除外),组必须尽可能小(在元素数量上)…但是上面的代码更好地描述了我想做的事情。cumsum的事情很接近,但不一样。只是要明确一点:
v
是先验存在的吗,或者如果我们提出了一个在随机抽样中抽取数组的解决方案,这是允许的吗?bucketIndex比你的bucketIndex快。@Roland我不是特别喜欢它令人惊讶。
其中(cs>N)
v
的长度中是
O(N)
,重复循环也是
O(N)
(长度的一部分,但并不比一部分好),因此整个函数在
v
的长度中应该是
O(N^2)
。具有简单循环的原始函数应该是
O(N)
长度为
v
。关于你的第三和第四个要点:是的,这是你想要的行为。
curSum <- curSum + v[i]
if(curSum > N){
  curSum <- 0
  index <- index + 1
}  
> bucketIndex (c(1, 1, 2, 1, 2, 1, 1, 2, 1, 5, 1), 3)
[1] 1 1 1 2 2 2 3 3 3 4 5
> bucketIndex (c(1, 1, 1, 2, 2, 1, 1, 2, 1, 5, 1), 3)
[1] 1 1 1 1 2 2 2 3 3 3 4
bucketIndex2 <- function(v, N) {
    index <- 1
    cs <- cumsum(v)
    bk.old <- 0
    o <- rep(0, length(v))

    repeat {
        bk <- suppressWarnings(min(which(cs > N)))
        o[(bk.old+1):min(bk,length(v))] <- index
        if (bk >= length(v)) break
        cs <- cs - cs[bk]
        index <- index + 1
        bk.old <- bk
    }

    o
}
for (i in 1:200) {
  v <- sample(sample(20,1), sample(50,1)+20, replace=TRUE)
  N <- sample(10,1)
  bi <- bucketIndex(v, N)
  bi2 <- bucketIndex2(v, N)
  if (any(bi != bi2)) {
    print("MISMATCH:")
    dump("v","")
    dump("N","")
  }
}