2014-01-14 4 views
2

Предположим, у меня есть data.frame следующим образом:Обобщить с rcpp

set.seed(45) 
DF <- data.frame(x=1:10, strata2013=sample(letters[1:3], 10, TRUE)) 

    x strata2013 
1 1   b 
2 2   a 
3 3   a 
4 4   b 
5 5   b 
6 6   a 
7 7   a 
8 8   b 
9 9   a 
10 10   a 

И я хотел бы, чтобы получить COUNTS для каждого уникального значения в столбце strata2013, затем, используя data.table (для скорости), можно было бы сделать это таким образом:

DT <- as.data.table(DF) 
DT[, .N, by=strata2013] 
    strata2013 N 
1:   b 4 
2:   a 6 

Теперь я хотел бы т и выполните это в Rcpp, как учебное упражнение. Я написал и опробовал приведенный ниже код, который должен обеспечивать тот же вывод, но вместо этого он дает мне ошибку. Вот код:

#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
NumericVector LengthStrata (CharacterVector uniqueStrata, DataFrame dataset) { 
    int n = uniqueStrata.size(); 
    NumericVector Nh(n); 
    Rcpp::CharacterVector strata=dataset["strate2013"]; 
    for (int i = 0; i < n; ++i) { 
    Nh[i]=strata(uniqueStrata(i)).size(); 
    } 
    return Nh; 
} 

Вот сообщение об ошибке:

conversion from 'Rcpp::Vector<16>::Proxy {aka Rcpp::internal::string_proxy<16>}' 
to 'const size_t { aka const long long unsigned int}' is ambiguous 

Что я делаю неправильно? Большое спасибо за Вашу помощь.

+1

Является ли это упрощенным примером? Потому что из вашего описания ist звучит как что-то, что можно сделать очень эффективно с R. – Roland

+0

Я знаю, что агрегированная функция может сделать это легко, но я просто хочу сравнить ... – Herimanitra

+0

Я не говорил о 'aggregate'. Существуют более эффективные альтернативы. Однако ваше описание не похоже на то, что ему нужно «aggregate». Но вы не очень четко объясняете в своем вопросе. – Roland

ответ

8

Если я правильно понял, вы надеетесь, что strata(uniqueStrata(i)) будет подмножать вектор, аналогичный тому, как работает подмножество R. К сожалению, это не так; вам придется выполнять подмножество «вручную». Rcpp пока не работает подмножество 'generic'.

Когда дело доходит до использования Rcpp, вы действительно хотите использовать стандартную библиотеку C++, где это возможно. Де-факто C++ способ генерации этих отсчетов состоял бы в использовании std::map (или std::unordered_map, если вы можете предположить C++ 11), с чем-то вроде следующего. Я включаю ориентир для интереса.

Примечание от Dirk: unordered_map действительно доступно от tr1 для pre-C++ 11, поэтому его можно включить, например, #include <tr1/unordered_map>

#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
IntegerVector LengthStrata(DataFrame dataset) { 
    Rcpp::CharacterVector strata = dataset["strata2013"]; 
    int n = strata.size(); 
    std::map<SEXP, int> counts; 
    for (int i = 0; i < n; ++i) { 
    ++counts[ strata[i] ]; 
    } 
    return wrap(counts); 
} 

/*** R 
library(data.table) 
library(microbenchmark) 
set.seed(45) 
DF <- data.frame(strata2013=sample(letters, 1E5, TRUE)) 
DT <- data.table(DF) 
LengthStrata(DF) 
DT[, .N, by=strata2013] 
microbenchmark(
    LengthStrata(DF), 
    DT[, .N, by=strata2013] 
) 
*/ 

дает мне

Unit: milliseconds 
         expr  min  lq median  uq  max neval 
      LengthStrata(DF) 3.267131 3.831563 3.934992 4.101050 11.491939 100 
DT[, .N, by = strata2013] 1.980896 2.360590 2.480884 2.687771 3.052583 100 

Rcpp раствор медленнее в этом случае вероятно, из-за времени, которое требуется, чтобы переместить R объекты и из контейнеров C++, но, надеюсь, это поучительно.

Помимо: Это, по сути, уже включены в Rcpp как функция сахара table, так что если вы хотите, чтобы пропустить опыт обучения, вы можете использовать предварительно запеченные решение, как

#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
IntegerVector LengthStrata(DataFrame dataset) { 
    Rcpp::CharacterVector strata = dataset["strata2013"]; 
    return table(strata); 
} 

Сахар улучшает скорость функции Rcpp:

Unit: milliseconds 
         expr  min  lq median  uq  max neval 
      LengthStrata(DF) 5.548094 5.870184 6.014002 6.448235 6.922062 100 
DT[, .N, by = strate2013] 6.526993 7.136290 7.462661 7.949543 81.233216 100 
+0

Как я могу узнать, что данная функция в R, подобная таблице(), доступна в «сахаре»? – Herimanitra

+1

Два основных способа: [сахара-виньетка] (http://cran.r-project.org/web/packages/Rcpp/vignettes/Rcpp-sugar.pdf) и просмотр [онлайн-документации для кислорода] (http://dirk.eddelbuettel.com/code/rcpp/html/dir_edae2c70406e9616e8689419d3d5106b.html) –

0

Я не уверен, что понимаю, что вы пытаетесь сделать. И когда strata вектор

 Rcpp::CharacterVector strata=df["strate2013"]; 

то я не уверен, что

 strata(uniqueStrata(i)).size() 

должен делать. Возможно, вы могли бы описать словами (или в R с некоторым примером кода и данных), что вы пытаетесь сделать здесь.

+0

Я переформулирую свой вопрос. Предположим, мы используем набор данных «mtcars» в R; данные (mtcars). Предположим, что mtcars $ cyl - это мои страты, которые мы считаем здесь символьным символом. mtcars $ cyl имеет 03 различных значений. То, что я хочу сделать, это иметь реализацию rcpp функции aggregate в R. Например, я хочу количество obs для каждого отдельного значения mtcars $ cyl – Herimanitra

+0

И что заставляет вас думать, что просто вызов 'size()' функция-член выполнит это? –

+0

strata (uniqueStrata (i)). Размер() должен подмножать вектор и дает его длину как функцию длины в R – Herimanitra

Смежные вопросы