Rcpp独特的订单输出

时间:2017-06-22 11:04:44

标签: r rcpp

我注意到Rcpp的独特功能命令结果

evalCpp("unique(IntegerVector::create(6,6,1,5,5,1))")
[1] 6 5 1
unique(c(6,6,1,5,5,1))
[1] 6 1 5

有没有办法避免这种情况? 谢谢你的帮助

3 个答案:

答案 0 :(得分:1)

如果查看(简短)源文件,您会看到它使用内部类IndexHash。我怀疑这个默认排序。

如果原始订单是最重要的,我想你可以自己写一个新的便利包装。它不是那么难:冒着浪费几个字节的内存的风险,分配一个临时的逻辑向量,使用标准的hashmap并在传入的向量上循环。对于每个值,询问hashmap是否已看到此值,存储布尔值答案。然后用它来索引原始矢量。

这已经在某处实现了。还可以查看Armadillo和Eigen的实用功能。

答案 1 :(得分:0)

这可能会帮助某人-仅适用于排序的向量。

  template <int ITYPE>
  Rcpp::Vector<ITYPE> unique(Rcpp::Vector<ITYPE> x) {
    int n = x.size();
    if (n == 1) return(x);

    Rcpp::Vector<ITYPE> res;
    res.push_back(x(0));


    for (int i = 1; i < n; i++) {
      if (x[i] != x(i - 1)) {
        res.push_back(x(i));
      } 
    }

    return res;
  }


答案 2 :(得分:0)

这就是我与issue一起尝试解决的问题的实现方式(使用this answer,并显示了其他各种解决方案和基准)。

  template < typename T, int RTYPE >
  inline SEXP sexp_unique( Rcpp::Vector< RTYPE > x ) {
    std::set< T > seen;
    auto newEnd = std::remove_if( x.begin(), x.end(), [&seen]( const T value ) {
      if ( seen.find( value ) != std::end( seen ) ) {
        return true;
      }
      seen.insert( value );
      return false;
    });
    x.erase( newEnd, x.end() );
    return x;
  }


  // returns unique values in their original input order
  inline SEXP get_sexp_unique( SEXP s ) {

    SEXP s2 = Rcpp::clone( s );

    switch( TYPEOF( s2 ) ) {
    case LGLSXP: {
      return sexp_unique< bool, LGLSXP >( s2 );
    }
    case REALSXP: {
      return sexp_unique< double, REALSXP >( s2 );
    }
    case INTSXP: {
      return sexp_unique< int, INTSXP >( s2 );
    }
    case STRSXP: {
      return sexp_unique< char* , STRSXP >( s2 );
    }
    default: Rcpp::stop("unknown vector type");
    }
    return 0;
  }