从 Rcpp 中的向量元素中擦除零

ann*_*ann 4 performance r vector subset rcpp

我编写了以下代码来从向量中删除零。我使用erase(i)Rcpp 库中的函数。

#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector erase_zero(NumericVector x) {
  for (int i = 0; i < x.size(); i++) {
    if (x[i] == 0) {
      x.erase(i);
    }
  }
  return x;
}
Run Code Online (Sandbox Code Playgroud)

一切都很好,现在问题是函数的输出,即

> erase_zero(c(0,1,2,3,0))
[1] 1 2 3
> erase_zero(c(0,0,1,2,3,0,0))
[1] 0 1 2 3 0
> erase_zero(c(0,0,0,1,2,3,0,0,0))
[1] 0 1 2 3 0
> erase_zero(c(0,0,0,0,1,2,3,0,0,0,0))
[1] 0 0 1 2 3 0 0
Run Code Online (Sandbox Code Playgroud)

我不知道为什么会发生这种情况。

阅读下面的所有答案后,我只是尝试了速度测试

> microbenchmark(erase_zero(s), erase_zero1(s), erase_zero_sugar(s))
Unit: microseconds
                expr    min      lq     mean median      uq    max neval
       erase_zero(s) 19.311 21.2790 22.54262 22.181 22.8780 35.342   100
      erase_zero1(s) 18.573 21.0945 21.95222 21.771 22.4680 36.490   100
 erase_zero_sugar(s)  1.968  2.0910  2.57070  2.296  2.5215 24.887   100
Run Code Online (Sandbox Code Playgroud)

erase_zero1是罗兰的第一个密码。此外,ThomasIsCoding 的 R 基础比其他基础都更高效。

Rol*_*and 5

erase改变向量的大小。这给出了预期的输出。

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector erase_zero(NumericVector x) {
  R_xlen_t n = x.size();
  for (R_xlen_t i = 0; i < n; i++) {
    if (x[i] == 0) {
      x.erase(i);
      i--;
      n--;
    }
  }
  return x;
}

/*** R
erase_zero(c(0,1,2,3,0))
erase_zero(c(0,0,1,2,3,0,0))
erase_zero(c(0,0,0,1,2,3,0,0,0))
erase_zero(c(0,0,0,0,1,2,3,0,0,0,0))
*/
Run Code Online (Sandbox Code Playgroud)

然而,你应该只使用一些 Rcpp 糖。它更有效:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector erase_zero_sugar(NumericVector x) {
  return x[x != 0];
}
Run Code Online (Sandbox Code Playgroud)

您还应该阅读为什么这些数字不相等