代码之家  ›  专栏  ›  技术社区  ›  DanY

除一个元素外向量的Rcpp最大值

  •  0
  • DanY  · 技术社区  · 7 年前

    在里面 Rcpp 我想求一个向量的最大值,但我想省略一个元素。

    vec <- 1:10
    ele <- 3
    max(vec[-ele])
    

    我在Rcpp中的(糟糕)版本:

    #include <Rcpp.h>
    using namespace Rcpp;
    
    // [[Rcpp::export]]
    double my_fun(NumericVector vec, int ele) {
        NumericVector vec_no_ele = clone(vec);
        vec_no_ele.erase(ele);
        return max(vec_no_ele);
    }
    
    0 回复  |  直到 7 年前
        1
  •  1
  •   thc    7 年前

    max

    // Coatless answer:
    // [[Rcpp::export]]
    double max_no_copy(NumericVector vec, int ele) {
      double temp = vec[ele-1];
      vec[ele-1] = vec[0];
      double result_max = max(vec);
      vec[ele-1] = temp;
      return result_max;
    }
    
    // humble for loop
    // [[Rcpp::export]]
    double max_except_for(NumericVector vec, int ele) {
      int vs = vec.size();
      double res = 0;
      for(int i=0; i<vs; i++) {
        if( i == ele-1 ) continue;
        if(vec[i] > res) res = vec[i];
      }
      return res;
    }
    

    R侧:

    x <- rnorm(1e8)
    x[1000] <- 1e9
    microbenchmark(max_except_for(x, 1000), max_no_copy(x, 1000), times=5)
    
    Unit: milliseconds
                        expr       min        lq     mean    median       uq       max neval cld
     max_except_for(x, 1000)  87.58906  93.56962  92.5092  93.59754  93.6262  94.16361     5  a 
        max_no_copy(x, 1000) 284.46662 292.57627 296.3772 296.78390 300.5345 307.52455     5   b
    
    
    identical(max_except_for(x, 1000), max_no_copy(x, 1000)) # TRUE
    
        2
  •  1
  •   coatless    7 年前

    @太空人在评论中提出了以下方法:

    在临时变量中保存要忽略的值。将该元素设置为零或某个小值,或与向量中的另一个值相同。计算最大值。根据温度变量重置元素。

    这将按如下方式实施:

    #include <Rcpp.h>
    using namespace Rcpp;
    
    // [[Rcpp::export]]
    double max_no_copy(NumericVector vec, int ele) {
      double temp = vec[ele];
    
      // Use a value already in vector
      vec[ele] = vec[0];
    
      // Find max value
      double result_max = max(vec);
    
      // Remove NA value
      vec[ele] = temp;
    
      return result_max;
    }
    

    测试:

    vec <- 1:10
    ele <- 2 # C++ indices start at 0 not 1. So, subtract.
    
    max_no_copy(vec, ele)
    # [1] 10
    

    稍后添加基准。。。

        3
  •  1
  •   DanY    7 年前

    来自@coatless的答案很好,建立在上面其他慷慨的评论的基础上。然而,它可以进一步推广@coatless使用中的值 vec[0]

    这是一个稍微广义的解,其中我使用相邻元素 ele 作为占位符,我检查一下 ele公司 在的索引中 vec vec.length()

    // calculate the max of a vector after omitting one element
    double max_except(NumericVector vec, int ele) {
        if (vec.length() == 1) stop("vec too short");
        if (ele < 0 | ele > vec.length()-1) stop("ele out of range");
        double temp = vec[ele];
        int idx = (ele > 0) ? ele-1 : ele+1;
        vec[ele] = vec[idx];
        double res = max(vec);
        vec[ele] = temp;
        return res;
    }