#r #csv #memory #fread #read.csv
#r #csv #память #fread #read.csv
Вопрос:
Я должен прочитать большой csv-файл (5,4 ГБ с 7 млн строк и 205 столбцов) в R. Я успешно прочитал его с помощью data.table::fread()
. Но я хочу знать, можно ли прочитать его с помощью basic read.csv()
?
Я пытался просто использовать грубую силу, но моя 16 ГБ ОЗУ не может вместить это. Затем я попытался использовать стратегию «разделяй и властвуй» (разбиение на фрагменты), как показано ниже, но она все равно не сработала. Как мне это сделать?
dt1 <- read.csv('./ss13hus.csv', header = FALSE, nrows = 721900, skip =1)
print(paste(1, 'th chunk completed'))
system.time(
for (i in (1:9)){
tmp = read.csv('./ss13hus.csv', header = FALSE, nrows = 721900, skip = i * 721900 1)
dt1 <- rbind(dt1, tmp)
print(paste(i 1, 'th chunk completed'))
}
)
Также я хочу знать, как fread()
работает, что может считывать все данные сразу и очень эффективно, независимо от того, с точки зрения памяти или времени?
Комментарии:
1. Я не думаю, что проблема в загрузке данных, она хранит данные, я думаю. Не говоря уже о том, что итеративная сборка с
rbind
всегда плоха: каждый раз, когда она что- то добавляет, R создает полную копию предыдущих данных. Для предыдущих сборок я предпочитаюdo.call(rbind.data.frame, lapply(fnames, read.csv))
, но я не знаю, решит ли это вашу проблему с большими данными. Если это не сработает, вы можете рассмотреть возможность одновременной обработки только части данных, объединить их (?), Сохранить и перейти к следующему пакету.2. Да, это называется чтением по частям. Однако ваша проблема связана с раздуванием памяти, вызванным тем, что вы не определили colClasses для ваших 205 столбцов (вам действительно нужно читать их все? это будет очень сложно)
3. Да, мне нужно прочитать все данные. Но как я могу избавиться от проблемы с памятью?
4. Определите colClasses для ваших 205 столбцов , целые числа для целых столбцов, числовые для двойных столбцов, коэффициенты для столбцов факторов. В противном случае вещи хранятся очень неэффективно. Пожалуйста, ознакомьтесь
?fread
и с руководством пользователя.
Ответ №1:
Ваша проблема не fread()
в том, что это раздувание памяти, вызванное тем, что вы не определили colClasses для всех ваших (205) столбцов. Но имейте в виду, что попытка прочитать все 5,4 ГБ в 16 ГБ ОЗУ на самом деле перегружает его в первую очередь, вы почти наверняка не сможете хранить весь этот набор данных в памяти; и даже если бы вы могли, вы будете выбрасывать память всякий раз, когда пытаетесь ее обработать. Итак, ваш подход не сработает, вам серьезно нужно решить, какое подмножество вы можете обрабатывать — какие поля вам абсолютно необходимы для начала:
- Определите colClasses для ваших 205 столбцов: ‘integer’ для целых столбцов, ‘numeric’ для двойных столбцов, ‘logical’ для логических столбцов, ‘factor’ для факторных столбцов. В противном случае данные хранятся очень неэффективно (например, миллионы строк очень расточительны), и результат может легко быть в 5-100 раз больше, чем необработанный файл.
- Если вы не можете вместить все 7 миллионов строк x 205 столбцов (что вы почти наверняка не сможете), тогда вам нужно будет сильно уменьшить объем памяти, выполнив некоторые или все из следующих действий:
- считывать и обрабатывать фрагменты (строк) (используйте
skip, nrows
аргументы и ищите SO для вопросов по fread в фрагментах) - отфильтруйте все ненужные строки (например, вы можете выполнить некоторую грубую обработку, чтобы сформировать индекс строки для интересующего вас подмножества строк, и импортировать этот гораздо меньший набор позже)
- удалите все ненужные столбцы (используйте fread
select
/drop
аргументы (укажите векторы имен столбцов для сохранения или удаления).
- считывать и обрабатывать фрагменты (строк) (используйте
- Убедитесь, что опция
stringsAsFactors=FALSE
, это заведомо плохое значение по умолчанию в R, которое вызывает бесконечную нехватку памяти. - Поля даты / времени в настоящее время считываются как символьные (что плохо сказывается на использовании памяти, миллионы уникальных строк). Либо полностью удалите столбцы даты для начала, либо считайте данные по частям и преобразуйте их с
fasttime
помощью пакета или стандартных базовых функций. - Посмотрите на аргументы для обработки NA. Возможно, вам пока захочется удалить столбцы с большим количеством NAS или грязные необработанные строковые поля.
Пожалуйста, смотрите ?fread
и data.table
документ для синтаксиса для приведенного выше. Если вы столкнулись с конкретной ошибкой, отправьте фрагмент, скажем, из 2 строк данных ( head(data)
), вашего кода и ошибки.
Комментарии:
1. Спасибо за ваш ответ! Но, похоже, вы неправильно поняли мой вопрос. Я уже успешно загрузил этот файл объемом 5,4 ГБ с помощью fread () (и там более чем на 30% больше свободной памяти), но не сработала функция R baisc ‘read.csv’
2. В настоящее время я задаюсь вопросом, возможно ли это просто с помощью базового ‘read.csv()’ для загрузки всех данных? Все должно быть в порядке, верно? Потому что fread() уже успешно загрузился.
3. Вы также можете написать код
read.csv()
для чтения файлов по частям (используйтеnrows
,skip
параметры).read.csv
также принимаетcolClasses
аргумент, и это помогает вам уменьшить использование памяти. Я предполагаю, что, учитываяfread()
работу, вам просто любопытно отладить причинуread.csv
дросселей. Попробуйтеread.csv(..., nrows=1000)
, а затем посмотрите, какие столбцы влияют на использование вашей памяти. Но, честно говоря,read.csv()
известно, что basic имеет плохую производительность при работе с большими файлами, поэтому я бы не стал тратить на это много времени, это единственная причина, по которой пользователи писалиdata.table::fread()
иreadr
пакеты, которые намного лучше.4. @HengchengZhu: Я не вижу особого смысла исследовать, почему
read.csv
производительность настолько ужасна (время выполнения и память). Почти все советы , которые я вам дал , также справедливы дляread.csv
. Если вы хотите, вы можете покопаться в нем и опубликовать свои результаты.read.csv
известно, что у него ужасная производительность, поэтому люди писали лучшие реализацииdata.table::fread()
,readr
пакеты и т.д.