Итак, у меня есть файл данных (разделенный точкой с запятой), в котором много деталей и неполные строки (ведущие к подавлению Access и SQL). Это набор данных на уровне округа, разбитый на сегменты, подсегменты и подсегменты (всего ~ 200 факторов) за 40 лет. Короче говоря, он огромен, и он не уместится в памяти, если я попытаюсь просто прочитать его.
Итак, мой вопрос заключается в следующем, учитывая, что мне нужны все округа, но только один год (и только самый высокий уровень сегмента ... что в итоге приводит к примерно 100000 строкам), что было бы наилучшим способом получить это сворачивание в R?
В настоящее время я пытаюсь вырезать ненужные годы с Python, обойдя ограничение на размер файла, читая и работая по одной строке за раз, но я бы предпочел решение только для R (пакеты CRAN в порядке). Есть ли аналогичный способ чтения файлов по частям в R?
Любые идеи очень приветствуются.
Обновить:
- Ограничения
- Требуется использовать мою машину, поэтому экземпляров EC2 нет
- Как можно больше R-only. Скорость и ресурсы в данном случае не важны ... при условии, что моя машина не взорвется ...
- Как вы можете видеть ниже, данные содержат смешанные типы, с которыми мне нужно работать позже.
- Данные
- Размер данных составляет 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 задыхается.
- Уменьшение карты
- Если честно, документация меня немного напугала, так что я не успел попробовать. Похоже, что для этого также требуется, чтобы объект был в памяти, что привело бы к поражению точки, если бы это было так.
- bigmemory
- Этот подход полностью связан с данными, но одновременно может обрабатывать только один тип. В результате все мои векторы символов упали при помещении в big.table. Если мне нужно разрабатывать большие наборы данных на будущее, я бы подумал об использовании только чисел, чтобы эта опция оставалась в живых.
- сканировать
- Сканирование, похоже, имело такие же проблемы с типами, как и большая память, но со всей механикой readLines. Короче говоря, на этот раз это просто не соответствовало требованиям.
sed
и / илиawk
создания урезанной версии CSV, которую вы можете прочитать напрямую. Поскольку это скорее обходной путь, чем ответ, я оставлю его как комментарий.fread
Функция гораздо быстрееread.table
. Используйте что-нибудь вроде,x = fread(file_path_here, data.table=FALSE)
чтобы загрузить его какdata.frame
объект.Ответы:
Моя попытка с
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)
источник
Я не являюсь экспертом в этом вопросе , но вы можете попробовать MapReduce , что в основном означает использование подхода «разделяй и властвуй». В R есть несколько вариантов для этого, в том числе:
В качестве альтернативы R предоставляет несколько пакетов для работы с большими данными, которые выходят за пределы памяти (на диск). Вероятно, вы могли бы загрузить весь набор данных в
bigmemory
объект и полностью выполнить сокращение в R. См. Http://www.bigmemory.org/ для набора инструментов, чтобы справиться с этим.источник
bigmemory
В этом случае вам может быть проще попробовать сначала.Да. Функция readChar () будет читать блок символов, не предполагая, что они оканчиваются нулем. Если вы хотите читать данные построчно, вы можете использовать readLines () . Если вы читаете блок или строку, выполняете операцию, а затем записываете данные, вы можете избежать проблемы с памятью. Хотя, если вы хотите запустить большой экземпляр памяти на Amazon EC2, вы можете получить до 64 ГБ ОЗУ. Это должно содержать ваш файл и много места для манипулирования данными.
Если вам нужно больше скорости, то рекомендация Шейна использовать Map Reduce очень хорошая. Однако, если вы выберете путь использования большого экземпляра памяти на EC2, вам следует взглянуть на многоядерный пакет для использования всех ядер на машине.
Если вы обнаружите, что хотите прочитать много гигабайт данных с разделителями в R, вам следует хотя бы изучить пакет sqldf, который позволяет импортировать непосредственно в sqldf из R, а затем работать с данными из R. Я обнаружил, что sqldf является одним из них. из самых быстрых способов импорта гигабайт данных в R, как упоминалось в предыдущем вопросе .
источник
Есть совершенно новый пакет под названием colbycol, который позволяет вам читать только те переменные, которые вам нужны, из огромных текстовых файлов:
http://colbycol.r-forge.r-project.org/
Он передает любые аргументы в read.table, поэтому комбинация должна позволить вам довольно точно определить подмножество.
источник
ff
Пакет представляет собой прозрачный способ иметь дело с большими файлами.Вы можете увидеть сайт пакета и / или презентацию о нем.
надеюсь, это поможет
источник
Вы можете импортировать данные в базу данных SQLite, а затем использовать RSQLite для выбора подмножеств.
источник
А как насчет использования
readr
иread_*_chunked
семьи?Итак, в вашем случае:
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 строки.источник
Вы изучили большую память ? Проверьте это и это .
источник
Возможно, вы сможете перейти на MySQL или PostgreSQL, чтобы избежать ограничений MS Access.
Подключить R к этим системам довольно просто с помощью коннектора базы данных на основе DBI (доступного в CRAN).
источник
scan () имеет как аргумент nlines, так и аргумент пропуска. Есть ли какая-то причина, по которой вы можете просто использовать это, чтобы читать фрагмент строк за раз, проверяя дату, чтобы увидеть, подходит ли она? Если входной файл упорядочен по дате, вы можете сохранить индекс, который сообщает вам, какими должны быть ваши пропуски и строки, что ускорит процесс в будущем.
источник
В наши дни 3,5 ГБ просто не так уж много, я могу получить доступ к машине с 244 ГБ ОЗУ (r3,8xlarge) в облаке Amazon за 2,80 доллара в час. Сколько часов у вас уйдет на то, чтобы понять, как решить проблему с помощью решений типа больших данных? Сколько стоит ваше время? Да, вам понадобится час или два, чтобы понять, как использовать AWS, но вы можете изучить основы на бесплатном уровне, загрузить данные и прочитать первые 10 тысяч строк в R, чтобы проверить, что он работает, а затем вы можете запустить большой экземпляр памяти, такой как r3.8xlarge, и прочтите все это! Просто мой 2с.
источник
Теперь, в 2017 году, я бы посоветовал перейти на Spark и SparkR.
синтаксис может быть написан простым, довольно похожим на dplyr способом
вполне подходит для небольшой памяти (небольшой в смысле 2017 года)
Однако начало работы может быть пугающим ...
источник
Я бы выбрал БД, а затем сделал несколько запросов для извлечения необходимых вам образцов через DBI.
Избегайте импорта CSV-файла размером 3,5 ГБ в SQLite. Или, по крайней мере, дважды проверьте, что ваш ОГРОМНЫЙ db соответствует ограничениям SQLite, http://www.sqlite.org/limits.html
У вас чертовски большая БД. Я бы выбрал MySQL, если вам нужна скорость. Но будьте готовы ждать много часов, пока завершится импорт. Если у вас нет нестандартного оборудования или вы пишете из будущего ...
Amazon EC2 может быть хорошим решением также для создания экземпляра сервера с R и MySQL.
мои две скромные копейки стоят.
источник