2014-12-20 4 views
3

Возможно глупый вопрос, но я охотился вокруг много для ответа и не смог найти один:прилагая к элементам внутри списка Rcpp

Я пытаюсь написать читателя файл, а-ля fread или read.delim, но реализован на C++ и подключен к R через Rcpp. Самый простой способ сделать это и есть она выдавала data.frame является у него производит List векторов - один для каждого столбца - и установите класс data.frame

List foo; 
foo.push_back(column); 
foo.attr("class") = "data.frame"; 
return foo; 

достаточно просто, и я сделал это до. К сожалению:

  1. Файл (ы), который я хочу прочитать, может иметь различное количество полей;
  2. Эта модель работает только элегантно, если вы читаете из столбца файла, в то время как фактические файлы, как правило, читаются по-разному.

Таким образом, ответ должен быть в состоянии определить Foo, а затем, для каждой строки я прочитал в, push_back() поле на каждой из базовых векторов Foo в:

List foo(1); 
foo[0].push_back("turnip"); 

К сожалению, я могу не получим, как это сделать: не представляется, что векторы-члены List могут быть pushed_back(), поскольку это приводит к ошибке «Rcpp :: Vector < 19> :: Proxy не имеет имени с именем push_back() "

Итак, мой вопрос: есть ли способ добавить к вектору в списке Rcpp? Или мой единственный вариант, чтобы прочитать файл в столбце за столбцом, добавив результирующие векторы к «foo» и укусить затраты на производительность, которые могут возникнуть в результате повторения итерации через [число столбцов] раз, а не один раз?

Надеюсь, этот вопрос достаточно ясен. С удовольствием отвечаю на любые вопросы.

ответ

4

Это полутвердая проблема, когда вы не знаете ни строк, ни столбцов заранее.

Несколько лет назад в проекте, оставленном в закрытом состоянии, я собрал свои данные в виде варианта (используя соответствующий класс Boost) и преобразован в конце.

В Rblpapi (к которому я внес какой-то другой код), Уит попробовал несколько подходов и в итоге определил his own helper functions, и я имел в виду дистилляцию/рефакторинг этого и обсудить его с Кевином - но этого еще не произошло ,

Так что не стесняйтесь, чтобы придумать что-то лучше :)

Вообще говоря, и вернуться к своей проблеме, мы часто получать данные строчной, часто через колл-спину. Типы Rcpp (типы обертки R) делают очень плохо, когда вы добавляете элемент по элементу - так что не делайте наивного push_back, так как вы закончите копирование много.

Так что если вы знаете свои типы, сделайте std::list над соответствующими std::vector<T> для данного T. Эти векторы вы можете расти. Как только у вас есть их, сборка Rcpp::List и, следовательно, Rcpp::DataFrame проще.

+1

Это имеет смысл.Итак, чтобы подвести итог; даже если он кажется неэффективным, наиболее эффективный подход, вероятно, повторяется многократно через файл, извлекающий каждый столбец поочередно как std :: vector, а затем добавив этот вектор в список целиком? –

+1

Во многих случаях вы можете делать чтение по-разному, увеличивая ваши структуры данных и конвертируя их в конце. Сделать это полностью _generally_ и _efficient_ сложно. –