Стратегии для чтения в CSV-файлах по частям? - PullRequest
19 голосов
/ 20 февраля 2012

У меня есть файл среднего размера (4 ГБ в формате CSV) на компьютере, на котором недостаточно ОЗУ для чтения (8 ГБ в 64-разрядной версии Windows).В прошлом я просто загружал его на узел кластера и считывал его, но мой новый кластер, по-видимому, произвольно ограничивает процессы до 4 ГБ ОЗУ (несмотря на аппаратное обеспечение, имеющее 16 ГБ на машину), поэтому мне нужно краткосрочное исправление.

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

Спасибо комментаторам за указание на то, что я могу потенциальночитать весь файл, используя некоторые уловки большой памяти: Быстрое чтение очень больших таблиц как кадров данных в R

Я могу придумать некоторые другие обходные пути (например, открыть в хорошем текстовом редакторе, отключить2/3 наблюдений, затем загрузите в R), но я бы предпочел их избегать, если это возможно.

Так что чтение его по частям все еще кажется наилучшим способом на данный момент.

Ответы [ 2 ]

23 голосов
/ 22 мая 2015

Я знаю, что это очень старая тема.Однако я недавно столкнулся с этим, потому что у меня была похожая проблема.После просмотра этой темы я заметил, что заметное решение этой проблемы не упоминалось.Используйте соединения!

1) Откройте соединение с вашим файлом

con = file("file.csv", "r")

2) Считайте куски кода с помощью read.csv

read.csv(con, nrows="CHUNK SIZE",...)

Примечание: определениеcolClasses значительно ускорит процесс.Обязательно укажите нежелательные столбцы как NULL.

3) Сделайте то, что вам нужно сделать

4) Повторите.

5) Закройте соединение

close(con)

Преимущество этого подхода - соединения.Если вы пропустите этот шаг, он, скорее всего, немного замедлит работу.Открывая соединение вручную, вы по существу открываете набор данных и не закрываете его, пока не вызовете функцию закрытия.Это означает, что, перебирая набор данных, вы никогда не потеряете свое место.Представьте, что у вас есть набор данных с 1e7 строк.Также представьте, что вы хотите загружать порцию из 1-5 строк одновременно.Поскольку мы открываем соединение, мы получаем первые 1e5 строк, выполняя read.csv(con, nrow=1e5,...), затем, чтобы получить второй блок, мы также запускаем read.csv(con, nrow=1e5,...) и т. Д.

Если мы не использовалисоединения мы получили бы первый блок таким же образом, read.csv("file.csv", nrow=1e5,...), однако для следующего блока нам понадобится read.csv("file.csv", skip = 1e5, nrow=2e5,...).Очевидно, что это неэффективно.Мы должны снова найти строку 1e5 + 1, несмотря на то, что мы только что прочитали строку 1e5.

Наконец, data.table::fread - это здорово.Но вы не можете передать это соединения.Так что этот подход не работает.

Надеюсь, это кому-нибудь поможет.

ОБНОВЛЕНИЕ

Люди продолжают голосовать за этот пост, поэтому я решил добавить одинболее краткая мысль.Новые readr::read_csv, как и read.csv, могут передаваться соединениям.Тем не менее, объявляется примерно в 10 раз быстрее.

11 голосов
/ 20 февраля 2012

Вы можете прочитать его в базе данных, скажем, с помощью RSQLite, а затем использовать оператор SQL для получения части.

Если вам нужна только одна часть, тогда read.csv.sql в пакете sqldf будет читатьданные в базу данных sqlite.Во-первых, он создает базу данных для вас, и данные не проходят через R, поэтому ограничения R не будут применяться (в данном случае это, прежде всего, RAM).Во-вторых, после загрузки данных в базу данных sqldf считывает вывод указанного оператора sql в R и, наконец, уничтожает базу данных.В зависимости от того, насколько быстро он работает с вашими данными, вы можете просто повторить весь процесс для каждой порции, если у вас их несколько.

Только одна строка кода выполняет все три шага, поэтому просто попробовать.

DF <- read.csv.sql("myfile.csv", sql=..., ...other args...)

См. ?read.csv.sql и ?sqldf, а также домашнюю страницу sqldf .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...