これは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
そして
ため、レコードのために、あなたのコードは、整数を返していませんでした
::runif
はdouble
の値を返します。そしてあなたの関数の戻り値の型は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
を
もちろん、私の間違い。完了しました。 – AgnieszkaTomczyk
これについて詳しく説明できますか?* "基本的なRcpp(Cライブラリなし)のみ使用できます" *? CとC++の標準ライブラリは、Rcppをインストールするたびに利用できるので、問題は何ですか? – nrussell
私は余分な数学ライブラリを意味します。例えばArmadillo – AgnieszkaTomczyk