2016-12-08 11 views
1

範囲から5つの整数、例えば1:10のランダムなベクトルを作成したいと考えています。 私は基本的なRcppだけを使うことができます。 (Cライブラリなし)Rcppで整数サンプルを生成する

現在、私は持っている:

#include <Rcpp.h> 
using namespace Rcpp; 
// [[Rcpp::export]] 
NumericVector test(){ 
NumericVector z(5); 
for (int i=0; i<5 ++i) 
z[i] = R::runif(1,10); 
return z; 
} 
/***R 
test() 
*/ 

しかし:

  • ユニークではありません

  • を整数ではありません。

+0

もちろん、私の間違い。完了しました。 – AgnieszkaTomczyk

+1

これについて詳しく説明できますか?* "基本的なRcpp(Cライブラリなし)のみ使用できます" *? CとC++の標準ライブラリは、Rcppをインストールするたびに利用できるので、問題は何ですか? – nrussell

+0

私は余分な数学ライブラリを意味します。例えばArmadillo – AgnieszkaTomczyk

答えて

5

これはstd::random_shuffleで簡潔に行うことができます。

#include <Rcpp.h> 

// [[Rcpp::export]] 
Rcpp::IntegerVector sample_int() { 
    Rcpp::IntegerVector pool = Rcpp::seq(1, 10); 
    std::random_shuffle(pool.begin(), pool.end()); 
    return pool[Rcpp::Range(0, 4)]; 
} 

出力例:

sample_int() 
# [1] 9 2 5 1 7 

sample_int() 
# [1] 1 10 5 3 8 

sample_int() 
# [1] 5 9 3 2 8 

そして

ため、レコードのために、あなたのコードは、整数を返していませんでした
  • ::runifdoubleの値を返します。そしてあなたの関数の戻り値の型はNumericVectorではなく

なあなたの例で使用したもの(1、...、10)のような小さな範囲を扱うとき、それは重要ではないもののIntegerVector、この

  • ました(特に、サンプリングされる要素の数が描画プールよりもはるかに小さい場合) std::random_shuffleの全体をの範囲でシャッフルするので、効率的ではありません。補助機能のカップルと、私たちはより良い行うことができます( std::randがあなたの目的のための「十分に」ランダムであると仮定した場合):

    #include <Rcpp.h> 
    
    // C++ 98 
    template <typename Iter, typename T> 
    inline void iota(Iter first, Iter last, T value) { 
        while (first != last) { 
         *first++ = value++; 
        } 
    } 
    
    template <typename T> 
    inline T pop_random(std::vector<T>& v) { 
        typename std::vector<T>::size_type pos = std::rand() % v.size(); 
        T res = v[pos]; 
    
        std::swap(v[pos], v.back()); 
        v.pop_back(); 
    
        return res; 
    } 
    
    // [[Rcpp::export]] 
    Rcpp::IntegerVector sample_int2(int n, int min, int max) { 
        Rcpp::IntegerVector res(n); 
        std::vector<int> pool(max + 1 - min); 
        iota(pool.begin(), pool.end(), min); 
    
        for (R_xlen_t i = 0; i < n; i++) { 
         res[i] = pop_random(pool); 
        } 
    
        return res; 
    } 
    

    と、比較のために元の溶液一般化:

    // [[Rcpp::export]] 
    Rcpp::IntegerVector sample_int(int n, int min, int max) { 
        Rcpp::IntegerVector pool = Rcpp::seq(min, max); 
        std::random_shuffle(pool.begin(), pool.end()); 
        return pool[Rcpp::Range(0, n - 1)]; 
    } 
    

    microbenchmark::microbenchmark(
        "sample_int" = sample_int(100, 1, 1e6), 
        "sample_int2" = sample_int2(100, 1, 1e6), 
        times = 300L 
    ) 
    # Unit: milliseconds 
    #   expr  min  lq  mean median  uq  max neval 
    # sample_int 20.639801 22.417594 23.603727 22.922765 23.735258 35.531140 300 
    # sample_int2 1.504872 1.689987 1.789866 1.755937 1.830249 2.863399 300 
    
    microbenchmark::microbenchmark(
        "sample_int" = sample_int(1e5, 1, 1e6), 
        "sample_int2" = sample_int2(1e5, 1, 1e6), 
        times = 300L 
    ) 
    # Unit: milliseconds 
    #   expr  min  lq  mean median  uq  max neval 
    # sample_int 21.08035 22.384714 23.295403 22.811011 23.282353 34.068462 300 
    # sample_int2 3.37047 3.761608 3.992875 3.945773 4.086605 9.134516 300 
    
    +3

    OP自身の要件である「ライブラリなし」に違反し、1分でOPによって獲得されます。あなたに何かを伝えます、私は何を知りたいと確信していません;-) –

    関連する問題