找到R中值较小的另一个元素的最近元素的最快方法

时间:2017-08-26 04:20:42

标签: r

我有这个循环,它将值赋给branch.from中的一个元素,该元素表示最接近(小于)的索引,其值小于branch中相应元素的值。

for (j in 2:length(branch)) {
  branch.from[j]<-max(which(branch[1:(j-1)]<=branch[j]))
}

分支有超过800万个元素,所以这需要我太长的时间。有更快的方法吗? 例如,

branch[1:20]<-c(1,54,25,54,22,54,36,54,43,54,40,54,27,54,34,54,26,54,32,54)

上面的代码给出了

branch.from[1:20]<-c(1,1,1,3,1,5,5,7,7,9,7,11,5,13,13,15,5,17,17,19)

Branching Example

1 个答案:

答案 0 :(得分:1)

一个Rcpp函数

我不确定是否有任何简单的方法来矢量化代码,因此Rcpp可能是最佳选择:

library(Rcpp); library(inline)

fun2 <- cppFunction(
    'std::vector<int> branchFrom(NumericVector branch)
{
    std::vector<int> branch_from;
    for(int j = branch.size() - 1; j > 0; j--) {
        int val = -1;
        for(int k = j - 1; k > -1; k--){
            if(branch[j] >= branch[k]){
                val = k;
                break;
            }
        }
        branch_from.push_back(val + 1);
    }
    branch_from.push_back(1);
    std::reverse(branch_from.begin(), branch_from.end());
    return branch_from;
}')

请注意,第二个for循环不一定会遍历所有k,因为一旦找到单个值x[k] <= x[j],它就会停止。

分析

使用原始实现封装在microbenchmark()中的microbenchmark软件包中的base,我得到以下信息:

Unit: microseconds
 expr     min       lq     mean  median      uq      max neval
 base 124.232 130.3555 152.7990 133.941 141.176 1048.724   100
 fun2   5.105   5.8145   8.0211   7.137   7.766   79.508   100

这表明与原始实施相比显着加快了速度。