Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Читать огромный CSV-файл, используя `read.csv` по стратегии "разделяй и властвуй"?

Автор вопроса: Hengcheng ZhuОтветов: 1

Я должен прочитать большой CSV-файл (5,4 ГБ с 7 млн ​​строк и 205 столбцов) в R. Я успешно прочитал его, используя data.table::fread(). Но я хочу знать, можно ли прочитать это, используя базовый 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(), который может считывать все данные сразу и очень эффективно, независимо от памяти или времени?

  • Я не думаю, что проблема в загрузке данных, я думаю, проблема в хранении данных. Не говоря уже о том, что итеративная сборка с rbind - это всегда плохо: каждый раз, когда она добавляет что-нибудь, R делает полную копию предыдущих данных. Для предыдущих сборок я предпочитаю do.call(rbind.data.frame, lapply(fnames, read.csv)), но я не уверен, что это решит вашу проблему с большими данными. Если это не сработает, вы можете рассмотреть возможность обработки только части данных за раз, агрегировать их (?), сохранить и перейти к следующему пакету. r2evans 15.04.2019
  • Да, это называется чтение кусками. Однако ваша проблема связана с раздуванием памяти, вызванным тем, что вы не определили colClasses для ваших 205 столбцов (вам действительно нужно читать их все? Это будет очень тесно) smci 15.04.2019
  • Да, мне нужно прочитать все данные. Но как я могу избавиться от проблемы с памятью? Hengcheng Zhu 15.04.2019
  • Определите colClasses для ваших 205 столбцов, целые числа для целых столбцов, числовые значения для двойных столбцов, факторы для столбцов факторов. В противном случае вещи хранятся очень неэффективно. См. ?fread и руководство. smci 15.04.2019

rcsvmemoryfread

Ответы

Ответ 1 · рейтинг 4 · smci

Ваша проблема не fread(), это раздувание памяти, вызванное тем, что не определены colClasses для всех ваших (205) столбцов. Но имейте в виду, что попытка прочитать все 5,4 ГБ в 16 ГБ ОЗУ, в первую очередь, напрягает, вы почти наверняка не сможете хранить весь этот набор данных в памяти; и даже если бы вы могли, вы будете сбрасывать память всякий раз, когда пытаетесь ее обработать. Таким образом, ваш подход не сработает, вам нужно серьезно решить, с каким подмножеством вы можете работать, какие поля вам абсолютно необходимы для начала работы:

  • Определите colClasses для ваших 205 столбцов: "integer" для целочисленных столбцов, "numeric" для двойных столбцов, "logical" для логических столбцов, "factor" для столбцов-факторов. В противном случае вещи хранятся очень неэффективно (например, миллионы строк очень расточительны), и результат может легко быть в 5-100 раз больше, чем необработанный файл.

  • Если вы не можете уместить все 7 млн строк x 205 столбцов (что почти наверняка не удастся), то вам придется агрессивно сократить объем памяти, выполнив некоторые или все из следующих действий:

    • read in and process chunks (of rows) (use skip, nrows arguments, and search SO for questions on fread in chunks)
    • отфильтровать все ненужные строки (например, вы можете выполнить некоторую грубую обработку, чтобы сформировать индекс строки из подмножества строк, которые вам нужны, и позже импортировать этот гораздо меньший набор)
    • удалить все ненужные столбцы (используйте аргументы fread select/drop (укажите векторы имен столбцов, которые нужно сохранить или удалить).
  • Убедитесь, что опция stringsAsFactors=FALSE - это заведомо плохой вариант по умолчанию в R, который вызывает бесконечные проблемы с памятью.

  • Поля даты/даты-времени в настоящее время читаются как символы (что плохо для использования памяти, миллионы уникальных строк). Либо полностью удалите столбцы даты для начала, либо прочитайте данные по частям и преобразуйте их с помощью пакета fasttime или стандартных базовых функций.
  • Посмотрите на аргументы для обработки NA. На данный момент вы можете отказаться от столбцов с большим количеством NA или беспорядочных необработанных строковых полей.

См. ?fread и data.table документ для синтаксис вышеперечисленного. Если вы столкнулись с конкретной ошибкой, опубликуйте фрагмент, скажем, 2 строки данных (head(data)), ваш код и ошибку.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы