Имея некоторые головные боли в строках обработки Rcpp, посмотрели на «Как протестировать Rcpp :: CharacterVector элементы для равенства», но ситуация немного сложнее.Rcpp: опрятный способ сравнения строк, полученных из кадра данных R?
Для иллюстрации предположим, что у нас есть кадр данных 200-строк имен и знаков, генерируемых случайным образом:
df = data.frame(name = paste("Person",
sample(LETTERS[1:10],200,rep=TRUE),sep=""),
mark = pmax(pmin(round(rnorm(200,60,15)),100),0),
stringsAsFactors=FALSE)
Я обнаружил, что следующий встроенный код (с помощью Rcpp) корректно отрабатывает сумму знаков для всех строк, где человек по имени является первым человеком, дан в кадре данных (т.е. ДФ $ имя [1] в R, или, что эквивалентно имя [0] в коде Rcpp):
library(inline)
fastfunc_good1 <- cxxfunction(
signature(DFin = "data.frame"),
plugin = "Rcpp",
body = '
Rcpp::DataFrame DF(DFin);
Rcpp::CharacterVector name = DF["name"];
Rcpp::IntegerVector mark = DF["mark"];
Rcpp::CharacterVector targetname(1);
Rcpp::CharacterVector thisname(1);
int n = name.length();
int tot = 0;
targetname = name[0];
std::string s_targetname = as<std::string>(targetname);
for (int i = 0; i < n; i++) {
thisname=name[i];
std::string s_thisname = as<std::string>(thisname);
if (s_thisname == s_targetname) {
tot = tot + mark[i];
}
}
return(Rcpp::wrap(tot));
')
Теперь я действительно хотят упростить это как можно больше, так как это грязно, чтобы определить отдельную переменную для повторного представить значение в имени [], принудить к std :: string, а затем выполнить сравнение. Там должен каким-то образом упрощения обозначений, так это больше похоже на следующее (что следует отметить, НЕ РАБОТАЕТ!) ...
fastfunc_bad1 <- cxxfunction(
signature(DFin = "data.frame"),
plugin = "Rcpp",
body = '
Rcpp::DataFrame DF(DFin);
Rcpp::CharacterVector name = DF["name"];
Rcpp::IntegerVector mark = DF["mark"];
int n = name.length();
int tot = 0;
for (int i = 0; i < n; i++) {
if (name[i] == name[0]) {
tot = tot + mark[i];
}
}
return(Rcpp::wrap(tot));
')
В конечном счете, цель этого мини-проекта обучения для меня, чтобы выяснить, как перебирать уникальные имена в df $ name, вычислять сумму метки для каждого из них и возвращать все (уникальные имена и соответствующие суммы) в качестве аккуратного фрейма данных. Я вычислил большинство гаек и болтов о том, как создавать и возвращать окончательный фрейм данных из других примеров - это всего лишь строка, описанная выше, которая вызывает у меня головные боли. Большое спасибо заранее за любые указатели!
Спасибо. Странно, что IntegerVector поддерживает простые операции, подобные этому, но CharacterVector этого не делает. Есть ли короткий путеводитель, где объясняется, какие основные операции не работают на CharacterVector/IntegerVector и, следовательно, требуют такого рода преобразования? Или должен ли первый шаг в коде Rcpp всегда переназначать данные на переменные C++ перед использованием? –
В качестве продолжения (немного слишком отрывочного сейчас, чтобы перейти к полному вопросу, поскольку я обдумываю его) ... Какова нынешняя лучшая практика с точки зрения использования кадров данных в Rcpp? Легкость, с которой можно «перехватить» кадр данных из R, очень аккуратная, но если в кадре данных имеется n столбцов, то считается, что данные должны быть разделены на n отдельных (C++) векторов перед использованием? В приведенном выше примере предлагается «да», поскольку, похоже, не поддерживается нотация, такая как df.name [i]. Но если ответ «да», значит ли это, что подмножество должно выполняться неявно, через логические векторы говорят? –
только один простой вопрос здесь, DF ["name"] возврат вектора или dataframe? потому что мы используем drop = TRUE right, если только один столбец подмножественно –