Получите тот же образец целых чисел из R cpp, что и базовый R - PullRequest
4 голосов
/ 07 февраля 2020

Можно ли получить те же sample целых чисел из Rcpp, что и из базовых R * sample?

Я пытался использовать Rcpp::sample и Rcpp::RcppArmadillo::sample, но они не возвращают одинаковые значения - пример кода ниже. Кроме того, секция Quick Example поста https://gallery.rcpp.org/articles/using-the-Rcpp-based-sample-implementation/ возвращает тот же образец из Rcpp и базы R, однако я не могу воспроизвести эти результаты (я прилагаю этот код в конце ).

Можно ли это сделать / что я делаю не так, пожалуйста?

Мои попытки:

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <RcppArmadilloExtensions/sample.h>

// [[Rcpp::export]]
Rcpp::IntegerVector mysamp1( int n) {
  Rcpp::IntegerVector v = Rcpp::sample(n, n);
  return v;
}

// [[Rcpp::export]]
Rcpp::IntegerVector mysamp2(int n) {  
  Rcpp::IntegerVector i = Rcpp::seq(1,n);
  Rcpp::IntegerVector v = wrap(Rcpp::RcppArmadillo::sample(i,n,false));
  return v;
}

// set seed https://stackoverflow.com/questions/43221681/changing-rs-seed-from-rcpp-to-guarantee-reproducibility
// [[Rcpp::export]]
void set_seed(double seed) {
  Rcpp::Environment base_env("package:base");
  Rcpp::Function set_seed_r = base_env["set.seed"];
  set_seed_r(std::floor(std::fabs(seed)));
}

// [[Rcpp::export]]
Rcpp::IntegerVector mysamp3( int n, int seed) {
  set_seed(seed); 
  Rcpp::IntegerVector v = Rcpp::sample(n, n);
  return v;
}


/***R
set.seed(1)
sample(10)
#  [1]  9  4  7  1  2  5  3 10  6  8
set.seed(1)
mysamp1(10)
#  [1]  3  4  5  7  2  8  9  6 10  1
set.seed(1)
mysamp2(10)
#  [1]  3  4  5  7  2  8  9  6 10  1
mysamp3(10, 1)
#  [1]  3  4  5  7  2  8  9  6 10  1

*/

Код из Использование реализации на основе RcppArmadillo образца R () сообщения галереи, которые возвращают FALSE в моей системе:

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadilloExtensions/sample.h>
using namespace Rcpp ;

// [[Rcpp::export]]
CharacterVector csample_char( CharacterVector x, 
                              int size,
                              bool replace, 
                              NumericVector prob = NumericVector::create()) {
  CharacterVector ret = RcppArmadillo::sample(x, size, replace, prob) ;
  return ret ;
}

/*** R
N <- 10
set.seed(7)
sample.r <- sample(letters, N, replace=T)

set.seed(7)
sample.c <- csample_char(letters, N, replace=T)

print(identical(sample.r, sample.c))
# [1] FALSE
*/

1 Ответ

6 голосов
/ 07 февраля 2020

Компиляция комментариев в ответ. Акрун отметил, что, задав RNGkind или RNGversion, мы можем повторить результаты. От DirkEddelbuettel; произошло «изменение в RNG R, которое произошло, потому что кто-то заметил смещение в, IIR C, использовании выборки (при очень большом N). Поэтому вы должны включить опцию в R, чтобы получить старую ( соответствие) поведение. "И RalfStubner указывает, что это известная проблема: https://github.com/RcppCore/RcppArmadillo/issues/250 и https://github.com/RcppCore/Rcpp/issues/945

В настоящее время R использует другой сэмплер по умолчанию, который приводит к разные результаты

RNGkind(sample.kind = "Rejection")
set.seed(1)
sample(10)
# [1]  9  4  7  1  2  5  3 10  6  8
set.seed(1)
mysamp1(10)
# [1]  3  4  5  7  2  8  9  6 10  1

Однако более раннюю версию можно использовать, используя

RNGkind(sample.kind = "Rounding")
#Warning message:
#  In RNGkind("Mersenne-Twister", "Inversion", "Rounding") : non-uniform 'Rounding' sampler used

set.seed(1)
sample(10)
# [1]  3  4  5  7  2  8  9  6 10  1
set.seed(1)
mysamp1(10)
# [1]  3  4  5  7  2  8  9  6 10  1
...