У меня есть большой вектор, содержащий кучу двойных элементов. Учитывая массив вектора процентиля, например percentile_vec = c(0.90, 0.91, 0.92, 0.93, 0.94, 0.95)
. В настоящее время я использую функцию Rcpp sort
для сортировки большого вектора, а затем найдите соответствующее значение процентиля. Вот основные коды:Как быстро вычислять процентиль в 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;
}
Я также попытаться вызвать функцию R quantile(x, c(.90, .91, .92, .93, .94, .95))
в Rcpp с помощью:
sub_percentile <- function (x)
{
return (quantile(x, c(.90, .91, .92, .93, .94, .95)));
}
source('C:/Users/~Call_R_function.R')
Испытание опирается на x=runif(1E6)
перечислены ниже:
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 ожидайте вычисления скоростной процентной доли, но я полагаю, std::sort(tmp.begin(), tmp.end())
замедляет скорость. Есть ли лучший способ получить быстрый результат с использованием C++, RCpp/RcppAramdillo? Благодарю.
Возможно, вы уже знаете об этом, но эти функции дают несколько разные результаты. – nrussell
Ну сортировка будет O (n log (n)), и вы не можете лучше, чем сортировка вектора. После этого вы выполняете линейный поиск по вектору, чтобы найти соответствующий элемент. Вероятно, вам удастся выполнить [двоичный поиск] (http://en.cppreference.com/w/cpp/algorithm/binary_search), поскольку у вас есть отсортированный вектор. – NathanOliver
@nurssell. Вы совершенно правы, мне также любопытно, как R рассчитывает 'процентили'. Я заметил, что для 'runif (1E6)' два результата имеют небольшую разницу, которая находится в пределах моего диапазона допуска. – Alvin