Ho un vettore grande contenente un gruppo di elementi doppi. Data una matrice di vettore percentile, ad esempio percentile_vec = c(0.90, 0.91, 0.92, 0.93, 0.94, 0.95)
. Attualmente sto usando la funzione Rcpp sort
per ordinare il vettore grande e quindi trovare il corrispondente valore percentile. Ecco i codici principali:Come eseguire il calcolo rapido del percentile in C++/Rcpp
// [[Rcpp::export]]
NumericVector sort_rcpp(Rcpp::NumericVector& x)
{
std::vector<double> tmp = Rcpp::as<std::vector<double>> (x); // or NumericVector tmp = clone(x);
std::sort(tmp.begin(), tmp.end());
return wrap(tmp);
}
// [[Rcpp::export]]
NumericVector percentile_rcpp(Rcpp::NumericVector& x, Rcpp::NumericVector& percentile)
{
NumericVector tmp_sort = sort_rcpp(x);
int size_per = percentile.size();
NumericVector percentile_vec = no_init(size_per);
for (int ii = 0; ii < size_per; ii++)
{
double size_per = tmp_sort.size() * percentile[ii];
double size_per_round;
if (size_per < 1.0)
{
size_per_round = 1.0;
}
else
{
size_per_round = std::round(size_per);
}
percentile_vec[ii] = tmp_sort[size_per_round-1]; // For extreme case such as size_per_round == tmp_sort.size() to avoid overflow
}
return percentile_vec;
}
Inoltre provo a chiamare funzione R quantile(x, c(.90, .91, .92, .93, .94, .95))
in Rcpp utilizzando:
sub_percentile <- function (x)
{
return (quantile(x, c(.90, .91, .92, .93, .94, .95)));
}
source('C:/Users/~Call_R_function.R')
Il test riposa per x=runif(1E6)
sono elencati di seguito:
microbenchmark(sub_percentile(x)->aa, percentile_rcpp(x, c(.90, .91, .92, .93, .94, .95))->bb)
#Unit: milliseconds
expr min lq mean median uq max neval
sub_percentile(x) 99.00029 99.24160 99.35339 99.32162 99.41869 100.57160 100
percentile_rcpp(~) 87.13393 87.30904 87.44847 87.40826 87.51547 88.41893 100
I si aspetta un calcolo rapido del percentile, ma suppongo che std::sort(tmp.begin(), tmp.end())
rallenti la velocità. C'è un modo migliore per ottenere un risultato veloce usando C++, RCpp/RcppAramdillo? Grazie.
Si può essere a conoscenza di questo già, ma queste funzioni producono risultati leggermente diversi. – nrussell
L'ordinamento è O (n log (n)) e non è possibile ottenere un vettore migliore. Successivamente stai facendo una ricerca lineare attraverso il vettore per trovare l'elemento corrispondente. Probabilmente ti conviene fare una [ricerca binaria] (http://en.cppreference.com/w/cpp/algorithm/binary_search) poiché hai un vettore ordinato. – NathanOliver
@nurssell Hai perfettamente ragione, sono anche curioso di sapere come R calcola il calcolo "percentile". Ho notato che per 'runif (1E6)', i due risultati hanno una leggera differenza, che rientra nell'intervallo di tolleranza. – Alvin