быстрее, чем scan () с Rcpp? - PullRequest
       19

быстрее, чем scan () с Rcpp?

8 голосов
/ 30 января 2012

Считывание ~ 5x10 ^ 6 числовых значений в R из текстового файла происходит на моем компьютере относительно медленно (несколько секунд, и я прочитал несколько таких файлов), даже с scan(..., what="numeric", nmax=5000) или подобными приемами.Может быть стоит попробовать оболочку Rcpp для такого рода задач (например, Armadillo имеет несколько утилит для чтения текстовых файлов)?Или я бы, скорее всего, тратил свое время на незначительное повышение производительности из-за ожидаемых перегрузок интерфейса?Я не уверен, что в настоящее время ограничивает скорость (внутреннюю производительность компьютера или что-то еще?). Это задача, которую я обычно повторяю много раз в день, и формат файла всегда одинаков, 1000 столбцов, около 5000 строк.

Вот пример файла для воспроизведения, если это необходимо.

nr <- 5000
nc <- 1000

m <- matrix(round(rnorm(nr*nc),3),nr=nr)

cat(m[1, -1], "\n", file = "test.txt") # first line is shorter
write.table(m[-1, ], file = "test.txt", append=TRUE,
            row.names = FALSE, col.names = FALSE)

Обновление : я пробовал read.csv.sql, а также load("test.txt", arma::raw_ascii), используя Armadillo, и оба были медленнее, чемscan решение.

Ответы [ 4 ]

8 голосов
/ 04 марта 2013

Я настоятельно рекомендую проверить fread в последней версии data.table. Версия на CRAN (1.8.6) пока не имеет fread (на момент публикации), поэтому вы сможете получить ее, если будете устанавливать из последнего источника в R-forge. Смотри здесь .

5 голосов
/ 30 января 2012

Пожалуйста, имейте в виду, что я не являюсь экспертом в области R, но, возможно, эта концепция применима и здесь: обычно чтение двоичных файлов выполняется намного быстрее, чем чтение текстовых файлов. Если ваши исходные файлы меняются не часто (например, вы используете разные версии вашего скрипта / программы для одних и тех же данных), попробуйте прочитать их через scan () один раз и сохранить их в двоичном формате (в руководстве есть глава о экспорт бинарных файлов). Оттуда вы можете изменить вашу программу для чтения двоичного ввода.

@ Rcpp: scan () и друзья, скорее всего, вызовут собственную реализацию (например, fscanf ()), поэтому написание собственных функций чтения файлов через Rcpp может не дать большого прироста производительности. Вы все еще можете попробовать это (и оптимизировать для ваших конкретных данных).

4 голосов
/ 31 января 2012

Salut Baptiste,

Ввод / вывод данных - огромная тема, настолько большая, что R поставляется со своим собственным руководством по вводу / выводу данных .

Основы Rфункции могут быть медленными, потому что они очень общие.Если вы знаете свой формат, вы можете легко написать себе более быстрый импортный адаптер.Если вы также знаете свои размеры, это еще проще, так как вам нужно только одно выделение памяти.

Редактировать: В первом приближении я бы написал десять строк в C ++.Откройте файл, прочитайте строку, разбейте ее на токены, присвойте vector<vector< double > > или что-то в этом роде.Даже если вы используете push_back() для отдельных векторных элементов, вы должны конкурировать с scan(), methinks.

Когда-то у меня был небольшой класс csv reader в C ++, основанный на коде самого Брайана Кернигана.Довольно общий (для CSV-файлов), довольно мощный.

Затем вы можете сжать производительность по своему усмотрению.

Дальнейшее редактирование: Этот SO вопрос содержит несколько указателей для случая чтения csv и ссылки на книгу Кернигана и Плаугера.

3 голосов
/ 30 января 2012

Да, вы почти наверняка можете создать что-то, что работает быстрее, чем read.csv / scan. Тем не менее, для высокопроизводительного чтения файлов существуют некоторые приемы, которые уже позволяют вам работать намного быстрее, поэтому все, что вы делаете, будет конкурировать с ними.

Как указывал Матиас, если ваши файлы меняются не очень часто, вы можете кэшировать их, вызвав save, а затем восстановить их с помощью load. (Обязательно используйте ascii = FALSE, так как чтение двоичных файлов будет быстрее.)

Во-вторых, как упомянул Габор, вы часто можете существенно повысить производительность, считывая файл в базу данных, а затем из этой базы данных в R.

В-третьих, вы можете использовать пакет HadoopStreaming , чтобы использовать возможности чтения файлов Hadoop.

Подробнее об этих методах см. Быстрое чтение очень больших таблиц в виде кадров данных в R .

...