【问题标题】:How do I sort a vector with NA values, and place the NA values at the end of the result in Rcpp or C++?如何对具有 NA 值的向量进行排序,并将 NA 值放在 Rcpp 或 C++ 中结果的末尾?
【发布时间】:2021-03-23 08:09:25
【问题描述】:

我正在尝试通过 Rcpp 包使用 C++ 优化 R 中的排序功能。我试图模仿的功能是sort(x, decreasing = TRUE, na.last = TRUE)。我已经能够使用以下代码实现第一个参数decreasing = TRUE

library(Rcpp)
x <- c(3, 7, 21, 6, NA, 1, 8, 7)


# base R sorting
sort(x, decreasing = TRUE, na.last = TRUE)
# [1] 21  8  7  7  6  3  1 NA

# Simple Rcpp sorting function
cppFunction("NumericVector sort_cpp(NumericVector x, bool decreasing = false) {
  NumericVector sorted = clone(x).sort(decreasing);
  return sorted;
}")
sort_cpp(x, decreasing = TRUE)
# [1] NA 21  8  7  7  6  3  1

我不太精通 C++ 或 Rcpp 包,无法在所有情况下将 NA 值放在最后。当我将decreasing 设置为 FALSE 时,默认情况下它会将 NA 值放在末尾,但是当它反转(设置为 TRUE)时,它会翻转整个向量并且 NA 值位于向量的前面。我已经尝试了一些成功的事情(同样,C++ 中的新手),并且能够在 C++ shell 中运行一些东西,但我无法成功地将它编码到 R 中。这主要是复制和粘贴自this question:

#include <iostream>
#include <algorithm>
#include <math.h>

using namespace std;

int main()
{
int n, k = 4, j; // k is number of elements
double x = -0.0;
double i = 0;
double swap = 0;//used in the function as a place holder and used for swapping between other variables
double a[100] = { (1/x) + (1/i), 2.3, 1/x *0, 1/i };//array of double elements // 1/i * 0 is NaN
//(1 / i) * 0


for (n = 0; n < (k - 1); n++) // for loop consists of variables and statements in order to arrange contents of array
{
  for (j = 0; j < k - n - 1; j++)
    {
      if (!std::isnan(a[j + 1]) && std::isnan(a[j]) || (a[j] > a[j + 1]))
        {
        swap = a[j];
        a[j] = a[j + 1];
        a[j + 1] = swap;

        }
    }
}

cout << "The list of sorted elements within the array, is: " << endl; /* Output message to user */
for (int i = 0; i < k; i++)// Loop up to number of elements within the array
{
    cout << a[i] << " ";/* Output contents of array */
}
cout << endl; //new line

return 0; 
}

有没有办法使用 Rcpp 包或类似的包将它导入 R?

【问题讨论】:

  • 很遗憾,无法告诉您有关 Rcpp 的任何信息。但是在 c++ 版本中,您可能会使用对 std::sort 函数的调用来替换循环,该函数可能会提供自定义比较函数。这可能看起来像这样:``` std::sort( std::begin(a), std::end(a), [](double d0,double d1) { if( isnan(d0) ) return false; if( isnan(d1) ) 返回真;返回 d0 here。
  • 感谢您的示例!我已经尝试将它合并到 Rcpp 中,但我仍然无法按降序排序。这是我所拥有的:
  • // [[Rcpp::plugins(cpp11)]] #include &lt;Rcpp.h&gt; #include &lt;iostream&gt; #include &lt;algorithm&gt; #include &lt;math.h&gt; using namespace Rcpp; using namespace std; // [[Rcpp::export]] NumericVector sort_cpp(NumericVector x, bool decreasing = false) { const int k = x.size(); NumericVector y = clone(x).sort(decreasing); std::sort(std::begin(y), std::end(y), [](double d0, double d1) { if( isnan(d0) ) return false; if( isnan(d1) ) return true; return d0 &lt; d1; }); return y; }
  • 抱歉没有正确格式化...

标签: c++ r sorting rcpp


【解决方案1】:

在卡巴的建议下,我想通了!它只需要更改用于确定排序顺序的符号。这是我能够在 Rcpp 中使用来生成 R 等效排序算法的内容。顺便说一句,我还没有测试它来确定与基础 R 相比的性能,因此可能有更好的方法来实现相同的结果。首先,保存要获取的 .cpp 文件:

// [[Rcpp::plugins(cpp11)]]
#include <Rcpp.h>
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace Rcpp;
using namespace std;

// [[Rcpp::export]]
NumericVector sort_cpp(NumericVector x, bool decreasing = false, bool nalast = false) {
  NumericVector y = clone(x);
  if(nalast) {
    if(decreasing) {
      std::sort(std::begin(y), std::end(y),
                [](double d0, double d1) {
                  if( isnan(d0) ) return false;
                  if( isnan(d1) ) return true;
                  return d0 > d1;
                });
    } else {
      std::sort(std::begin(y), std::end(y),
                [](double d0, double d1) {
                  if( isnan(d0) ) return false;
                  if( isnan(d1) ) return true;
                  return d0 < d1;
                });
    }
  } else {
    y.sort(decreasing);
  }
  return y;
}

然后使用Rcpp::sourceCpp()编译函数使用。我没有合并 na.last = FALSE 的情况,其中 NA 值将被删除。这超出了我的使用范围,但是如果将来偶然发现这个问题,这应该可以帮助其他人入门!

【讨论】:

    猜你喜欢
    • 2018-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-29
    • 1970-01-01
    • 2021-11-10
    • 2021-05-28
    • 1970-01-01
    相关资源
    最近更新 更多