Обрезка огромного (3,5 ГБ) CSV-файла для чтения в R

Итак, у меня есть файл данных (разделенный точкой с запятой), который содержит много деталей и неполных строк (что приводит к засорению Access и SQL). Это набор данных на уровне округов, разбитый на сегменты, подсегменты и подсегменты (всего ~ 200 факторов) в течение 40 лет. Короче говоря, он огромен и не умещается в памяти, если я попытаюсь просто прочитать его.

Итак, мой вопрос заключается в следующем: учитывая, что я хочу, чтобы все округа, но только один год (и только самый высокий уровень сегмента ... привели к концу около 100 000 строк), каким был бы лучший способ идти о получении этого накопительного пакета в R?

В настоящее время я пытаюсь отбросить ненужные годы с помощью Python, чтобы обойти ограничение размера файла, читая и работая по одной строке за раз, но я бы предпочел решение только для R (пакеты CRAN в порядке). Есть ли аналогичный способ чтения файлов по частям в R?

Любые идеи будут с благодарностью.

Update:

  • Ограничения
    • Требуется использовать мой компьютер, поэтому экземпляры EC2 не нужны
    • По возможности только R Скорость и ресурсы не имеют значения в этом случае ... при условии, что моя машина не взорвется ...
    • Как вы можете видеть ниже, данные содержат смешанные типы, с которыми мне нужно работать позже
  • Данные
    • Данные имеют размер 3,5 ГБ, около 8,5 миллионов строк и 17 столбцов
    • Пару тысяч строк (~ 2k) искажены, только один столбец вместо 17
      • Они совершенно не важны и могут быть удалены
    • Мне нужно только ~ 100 000 строк из этого файла (см. ниже)

Пример данных:

County; State; Year; Quarter; Segment; Sub-Segment; Sub-Sub-Segment; GDP; ...
Ada County;NC;2009;4;FIRE;Financial;Banks;80.1; ...
Ada County;NC;2010;1;FIRE;Financial;Banks;82.5; ...
NC  [Malformed row]
[8.5 Mill rows]

Я хочу выделить несколько столбцов и выбрать два из 40 доступных лет (2009-2010 гг. с 1980-2020 гг.), чтобы данные могли вписаться в R:

County; State; Year; Quarter; Segment; GDP; ...
Ada County;NC;2009;4;FIRE;80.1; ...
Ada County;NC;2010;1;FIRE;82.5; ...
[~200,000 rows]

Результаты:

Поработав со всеми сделанными предложениями, я решил, что readLines, предложенные JD и Marek, будут работать лучше всего. Я дал Мареку чек, потому что он дал пример реализации.

Я воспроизвел слегка адаптированную версию реализации Марека для моего окончательного ответа здесь, используя strsplit и cat, чтобы оставить только нужные мне столбцы.

Следует также отметить, что это НАМНОГО менее эффективно, чем Python ... как, например, Python обрабатывает файл 3.5 ГБ за 5 минут, в то время как R занимает около 60 ... но если все есть R, то это билет.

## Open a connection separately to hold the cursor position
file.in <- file('bad_data.txt', 'rt')
file.out <- file('chopped_data.txt', 'wt')
line <- readLines(file.in, n=1)
line.split <- strsplit(line, ';')
# Stitching together only the columns we want
cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE)
## Use a loop to read in the rest of the lines
line <- readLines(file.in, n=1)
while (length(line)) {
  line.split <- strsplit(line, ';')
  if (length(line.split[[1]]) > 1) {
    if (line.split[[1]][3] == '2009') {
        cat(line.split[[1]][1:5], line.split[[1]][8], sep = ';', file = file.out, fill = TRUE)
    }
  }
  line<- readLines(file.in, n=1)
}
close(file.in)
close(file.out)

Сбои по подходу:

  • sqldf
    • Это определенно то, что я буду использовать для решения проблем такого типа в будущем, если данные будут правильно сформированы. Однако, если это не так, SQLite задыхается.
  • MapReduce
    • Честно говоря, документы немного запугали меня, поэтому я не удосужился попробовать. Это выглядело так, как будто требовалось, чтобы объект также находился в памяти, что могло бы победить, если бы это было так.
  • bigmemory
    • Этот подход четко связан с данными, но он может обрабатывать только один тип за раз. В результате все мои векторы персонажей сбрасываются, когда они помещаются в big.table. Однако если мне нужно спроектировать большие наборы данных для будущего, я бы хотел использовать только цифры, чтобы сохранить эту опцию.
    сканирования литий>
    • Сканирование, похоже, имело те же проблемы с типом, что и большая память, но со всей механикой readLines. Короче говоря, на этот раз это не отвечало всем требованиям.
r csv
84 голоса | спросил FTWynn 22 J0000006Europe/Moscow 2010, 20:00:09

12 ответов


0

Моя попытка с readLines. Этот фрагмент кода создает csv с выбранными годами.

file_in <- file("in.csv","r")
file_out <- file("out.csv","a")
x <- readLines(file_in, n=1)
writeLines(x, file_out) # copy headers

B <- 300000 # depends how large is one pack
while(length(x)) {
    ind <- grep("^[^;]*;[^;]*; 20(09|10)", x)
    if (length(ind)) writeLines(x[ind], file_out)
    x <- readLines(file_in, n=B)
}
close(file_in)
close(file_out)
ответил Marek 24 J0000006Europe/Moscow 2010, 12:45:49
0
  

Есть ли аналогичный способ чтения файлов по частям в R?

Да. Функция readChar () будет читать блок символов, не предполагая, что они заканчиваются нулем. Если вы хотите читать данные в строке за раз, вы можете использовать readLines () . Если вы читаете блок или строку, делаете операцию, а затем записываете данные, вы можете избежать проблемы с памятью. Хотя, если вы хотите запустить большой экземпляр памяти на Amazon EC2, вы можете получить до 64 ГБ ОЗУ. Это должно держать ваш файл плюс много места для манипулирования данными.

Если вам нужна большая скорость, то рекомендация Шейна использовать Map Reduce очень хорошая. Однако, если вы идете по пути использования большого экземпляра памяти в EC2, вы должны взглянуть на многоядерный пакет для использования всех ядер на машине.

Если вам захочется прочитать много гигабайт данных с разделителями в R, вам следует хотя бы изучить пакет sqldf, который позволяет импортировать напрямую в sqldf из R, а затем работать с данными из R. Я нашел sqldf быть одним из самых быстрых способов импорта концертов данных в R, как указано в этот предыдущий вопрос .

ответил JD Long 22 J0000006Europe/Moscow 2010, 22:47:13
0

Я не эксперт в этом, но вы можете попробовать MapReduce , что в основном, это означает «разделяй и властвуй». R имеет несколько вариантов для этого, в том числе:

  1. mapReduce (чистый R)
  2. RHIPE (где используется Hadoop ); см. пример 6.2.2 в документации для примера подмножество файлов

Кроме того, R предоставляет несколько пакетов для работы с большими данными, которые выходят за пределы памяти (на диск). Возможно, вы могли бы загрузить весь набор данных в объект bigmemory и полностью выполнить сокращение в R. См. http://www.bigmemory.org/ для набора инструментов для решения этой проблемы.

ответил Shane 22 J0000006Europe/Moscow 2010, 20:14:20
0

Пакет ff - это прозрачный способ работы с большими файлами.

Вы можете увидеть пакет веб-сайт и /или представление об этом.

Надеюсь, это поможет

ответил Ali 9 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowSun, 09 Sep 2012 18:37:11 +0400 2012, 18:37:11
0

Вы можете импортировать данные в базу данных SQLite а затем используйте RSQLite , чтобы выберите подмножества.

ответил Marek 22 J0000006Europe/Moscow 2010, 20:36:49
0

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

http://colbycol.r-forge.r-project.org/

Он передает любые аргументы в read.table, поэтому комбинация должна позволять вам довольно тесно использовать подмножество.

ответил Ari B. Friedman 4 Maypm12 2012, 16:22:34
0

Как насчет использования readr и read_*_chunked family?

Так что в вашем случае:

TestFile.CSV

County; State; Year; Quarter; Segment; Sub-Segment; Sub-Sub-Segment; GDP
Ada County;NC;2009;4;FIRE;Financial;Banks;80.1
Ada County;NC;2010;1;FIRE;Financial;Banks;82.5
lol
Ada County;NC;2013;1;FIRE;Financial;Banks;82.5

Фактический код

require(readr)
f <- function(x, pos) subset(x, Year %in% c(2009, 2010))
read_csv2_chunked("testfile.csv", DataFrameCallback$new(f), chunk_size = 1)

Это относится к f к каждому чанку, запоминая имена столбцов и в конце объединяя отфильтрованные результаты. См. ?callback который является источником этого примера.

Это приводит к:

# A tibble: 2 × 8
      County State  Year Quarter Segment `Sub-Segment` `Sub-Sub-Segment`   GDP
*      <chr> <chr> <int>   <int>   <chr>         <chr>             <chr> <dbl>
1 Ada County    NC  2009       4    FIRE     Financial             Banks   801
2 Ada County    NC  2010       1    FIRE     Financial             Banks   825

Вы даже можете увеличить chunk_size, но в этом примере всего 4 строки.

ответил Rentrop 2 Maypm17 2017, 12:50:58
0

Вы изучили bigmemory ? Проверьте этого и this> nofol>.

ответил George Dontas 22 J0000006Europe/Moscow 2010, 20:30:39
0

Возможно, вы можете перейти на MySQL или PostgreSQL, чтобы уберечь себя от ограничений MS Access.

Подключить R к этим системам довольно просто с помощью DBI (доступно на CRAN) на основе соединителя базы данных.

ответил FloE 22 J0000006Europe/Moscow 2010, 20:36:42
0

В наши дни 3,5 ГБ не так уж и велики, я могу получить доступ к машине с 244 ГБ ОЗУ (r3.8xlarge) в облаке Amazon за 2,80 доллара в час. Сколько часов вам понадобится, чтобы понять, как решить проблему, используя решения типа больших данных? Сколько стоит ваше время? Да, вам понадобится час или два, чтобы понять, как использовать AWS, но вы можете изучить основы бесплатного уровня, загрузить данные и прочитать первые 10k строк в R, чтобы проверить, как это работает, а затем вы можете запустить большой экземпляр памяти типа r3.8xlarge и читать все это в! Просто мой 2с.

ответил Sean 12 +04002014-10-12T20:20:00+04:00312014bEurope/MoscowSun, 12 Oct 2014 20:20:00 +0400 2014, 20:20:00
0

Теперь, 2017, я бы предложил перейти на spark и sparkR.

  • синтаксис может быть написан простым, довольно похожим на dplyr способом

  • он очень хорошо вписывается в небольшую память (в смысле 2017 - маленькую)

Тем не менее, это может быть пугающим опытом, чтобы начать ...

ответил Ott Toomet 26 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 26 Sep 2017 06:39:49 +0300 2017, 06:39:49
0

Я бы выбрал БД, а затем сделал несколько запросов, чтобы извлечь нужные образцы через DBI.

Пожалуйста, не импортируйте CSV-файл размером 3,5 ГБ в SQLite. Или, по крайней мере, дважды проверьте, что ваша ОГРОМНАЯ БД соответствует ограничениям SQLite, http://www.sqlite.org/limits.html

Это чертовски большая БД у вас есть. Я бы пошел на MySQL, если вам нужна скорость. Но будьте готовы подождать много часов до завершения импорта. Если у вас нет нестандартного оборудования или вы пишете из будущего ...

Amazon EC2 может быть хорошим решением и для создания экземпляра сервера под управлением R и MySQL.

мои две скромные копейки стоит.

ответил Liborio Francesco Cannici 23 J0000006Europe/Moscow 2010, 01:14:05

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132