Могу ли я создавать векторы из столбцов DataFrame на лету в RCpp

У меня надуманный вопрос о Rcpp, я обычно использую много объектов DataFrame для создания xxxVector в C++ и экспортирую их обратно в R. Иногда мне приходится иметь дело с 10 столбцами, которые я должен определить сам, например:

export [[Rcpp::export]]
List myFunction(DataFrame df){
   NumericVector a = df["a"], b = df["b"], c = df["c"];
   IntegerVector a2 = df["a2"], b2 = df["b2"], c2 = df["c2"];
   CharacterVector a3 = df["a3"], b3 = df["b3"], c3 = df["c3"];

   const int N = df.nrows();
   LogicalVector out(N),out1(N);

   for(unsigned int i = 0; i<N; ++i){
      //here I do what I want to do
   }

   return(List::create(_["out"]=out, _["out1"]=out1));
}

Если список объявлений длинный со сложными именами, объявления занимают много времени. Я мог бы просто не объявлять a,b,c,... и работать с df["a"],..., но это было бы еще дольше. Тогда мой вопрос (и это вполне может быть ересью) есть ли способ автоматически определить эти векторные столбцы? Я подумал, что, поскольку у нас есть DataFrame, который представляет собой список указателей на столбцы, возможно, его можно будет автоматизировать...


person statquant    schedule 19.07.2013    source источник
comment
Так сделать имена короче?   -  person Dirk Eddelbuettel    schedule 19.07.2013
comment
Не может быть переменных длиной менее 1 символа... :). Но по идее автоматического объявления это вообще выполнимо?   -  person statquant    schedule 19.07.2013
comment
Вы пробовали индексировать по (содроганию, не рекомендуется) положению? Или использовать хэш-функцию? :-)   -  person Dirk Eddelbuettel    schedule 19.07.2013
comment
Нет... возможно, вы уже потеряли меня, но вы имеете в виду такие вещи, как df[i][j], где i будет местом, скажем, b, а j будет иметь доступ к j элементу вектора? Если это так, я мог бы это сделать, но я не хочу этого делать, потому что это сделало бы код нечитаемым (даже для меня самого).   -  person statquant    schedule 19.07.2013


Ответы (1)


Похоже, если бы это был код R, вы хотите превратить фрейм данных в «среду». Я не вижу никакого способа сделать что-то подобное на C++ - разница между интерпретируемым и компилируемым языком.

Если вы просто хотите автоматизировать генерацию шаблонного кода, вы можете попробовать сделать это в R. Что-то вроде строк

genDfBoilerplate <- function( coltypes, dfname="df" )
{
  ## coltypes is a named character vector with elements  "Integer", "Logical", 
  ##   "Character", etc.
  ## and names(coltypes) are the dataframe column names
  ## the name of the dataframe is dfname (default: df)
  bp = character(0)
  for( name in names(coltypes) )
  {
    decl <- sprintf('    const %sVector& %s(%s["%s"]);', coltypes[name], name, dfname, name)
    bp <- append(bp, decl)
  }
  paste(bp, sep="", collapse="\n")
}

Например:

> coltypes = c(a="Integer", b="Numeric")
> bp = genDfBoilerplate(coltypes)
> cat(bp)
    const IntegerVector& a(df["a"]);
    const NumericVector& b(df["b"]);

(Я объявил переменные как константные ссылки для максимальной эффективности. Очевидно, вы можете изменить это в зависимости от специфики вашей функции (например, если кадр данных передается по ссылке, и вам нужна локальная копия столбца, чтобы изменить его. ))

Я оставляю вам вопрос о том, как вы получите шаблон в своем функциональном коде Rcpp; копирование/вставка - одно из решений.

person c-urchin    schedule 19.07.2013
comment
Спасибо за ваш ответ, я сомневался в возможности сделать это, но, поскольку вы можете передать среду с R на C++, я надеялся, что знающие люди смогут найти способ... По вашему предложению не уверен, что reference IntegerVector& очень полезен, поскольку DataFrameis список указателей уже есть, но идея хорошая, теперь я буду делать это - person statquant; 19.07.2013
comment
Если df[a] возвращает только интеллектуальный указатель, то ссылка не будет иметь большого значения; но это единственный способ в C++ гарантировать, что глубокая копия не будет сделана. Если вы предпочитаете синтаксис значения, просто измените genDfBoilerplate по своему вкусу. - person c-urchin; 19.07.2013