Обычно мне приходится работать с большими пространственными данными, поэтому ожидается высокая скорость и эффективность памяти. Предположим, я хочу изменить некоторые числовые c столбцы фрейма данных с помощью самоопределяемой функции в R cpp, меня смущает механизм ссылок и копирования в C ++ и R cpp. Не могли бы вы помочь мне с помощью трех приведенных ниже минимальных примеров кода ответить на следующие вопросы:
Является ли updateDF3 лучшей функцией для выполнения такой задачи с максимальной скоростью и минимальным объемом памяти? Эта функция изменена на основе аналогичного вопроса здесь , но я не понимаю предупреждение, данное автором: «С этим подходом связаны проблемы. Ваш исходный фрейм данных и тот, который вы создали, имеют одинаковые векторы. и может случиться так плохое ". Если я использую эту функцию только для такой подфункции как updateDF3 и вызываю ее из R, безопасно ли это?
Почему разница в производительности updateDF1 и updateDF2 незначительна? В чем разница между передачей параметра со ссылкой (&) или без нее?
Является ли функция закодированной в пуле, и есть другой способ, например DataFrame out = clone (df), tmpstr = asstd :: string (colnames [v])?
Заранее спасибо.
#include <Rcpp.h>
#include <iostream>
using namespace Rcpp;
using namespace std;
// [[Rcpp::export]]
bool contains(CharacterVector x, std::string y) {
return std::find(x.begin(), x.end(), y)!=x.end();
}
// [[Rcpp::export]]
DataFrame updateDF1(DataFrame df, Nullable<Rcpp::CharacterVector> vars=R_NilValue) {
DataFrame out=clone(df);
string tmpstr;
NumericVector tmpv;
if(vars.isNotNull()){
CharacterVector selvars(vars);
for(int v=0;v<selvars.size();v++){
tmpstr=as<std::string>(selvars[v]);
tmpv=df[tmpstr];
tmpv=tmpv+1.0;
out[tmpstr]=tmpv;
}
}
return out;
}
// [[Rcpp::export]]
DataFrame updateDF2(DataFrame& df, Nullable<Rcpp::CharacterVector> vars=R_NilValue) {
DataFrame out=clone(df);
string tmpstr;
NumericVector tmpv;
if(vars.isNotNull()){
CharacterVector selvars(vars);
for(int v=0;v<selvars.size();v++){
tmpstr=as<std::string>(selvars[v]);
tmpv=df[tmpstr];
tmpv=tmpv+1.0;
out[tmpstr]=tmpv;
}
}
return out;
}
// [[Rcpp::export]]
List updateDF3(DataFrame& df, Nullable<Rcpp::CharacterVector> vars=R_NilValue) {
List out(df.size());
CharacterVector colnames=df.attr("names");
string tmpstr;
NumericVector tmpv;
for(int v=0;v<df.size();v++){
if(vars.isNotNull()){
CharacterVector selvars(vars);
tmpstr=as<std::string>(colnames[v]);
if(contains(selvars,tmpstr)){
tmpv=df[tmpstr];
tmpv=tmpv+1.0;
out[v]=tmpv;
}else{
out[v]=df[tmpstr];
}
}else{
out[v]=df[tmpstr];
}
}
out.attr("class") = df.attr("class") ;
out.attr("row.names") = df.attr("row.names") ;
out.attr("names") = df.attr("names") ;
return out;
}
/*** R
df=as.data.frame(matrix(1:120000000,nrow=10000000))
names(df)=paste("band",1:ncol(df),sep="_")
df=cbind(x="charcol",df)
microbenchmark::microbenchmark(
x1<<-updateDF1(df,vars=names(df)[-1]),
x2<<-updateDF2(df,vars=names(df)[-1]),
x3<<-updateDF3(df,vars=names(df)[-1]),
times=10
)
identical(x1,x2)
identical(x1,x3)
*/
##performance
#Unit: milliseconds
# expr min lq mean median
# x1 <<- updateDF1(df, vars = names(df)[-1]) 587.6023 604.9242 711.8981 651.1242
# x2 <<- updateDF2(df, vars = names(df)[-1]) 581.7129 641.2876 882.9999 766.9354
# x3 <<- updateDF3(df, vars = names(df)[-1]) 406.1824 417.5892 542.2559 420.8485