Быстрое чтение очень больших таблиц как фреймов данных

У меня есть очень большие таблицы (30 миллионов строк), которые я хотел бы загрузить как фреймы данных в R. read.table() имеет много удобных функций, но похоже, что в реализации есть много логики, которая может замедлить работу. В моем случае я предполагаю, что заранее знаю типы столбцов, таблица не содержит заголовков столбцов или имен строк и не содержит каких-либо патологических символов, о которых мне нужно беспокоиться.

Я знаю, что чтение таблицы в виде списка с использованием scan() может быть довольно быстрым, например:

datalist <- scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0)))

Но некоторые из моих попыток преобразовать это в фрейм данных, похоже, снижают производительность вышеуказанного в 6 раз:

df <- as.data.frame(scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0))))

Есть ли лучший способ сделать это? Или, возможно, совсем другой подход к проблеме?


person eytan    schedule 13.11.2009    source источник


Ответы (11)


Обновление, появившееся несколько лет спустя

Это старый ответ, и R пошел дальше. Настройка read.table для более быстрой работы имеет мало пользы. Возможны следующие варианты:

  1. Использование vroom из пакета tidyverse vroom для импорта данных из файлов csv / с разделителями табуляцией прямо в тиббл R. См. ответ Гектора.

  2. Использование fread в _ 5_ для импорта данных из файлов csv / с разделителями табуляции непосредственно в R. См. ответ отmnel.

  3. Использование read_table в _ 7_ (на CRAN с апреля 2015 г.). Это работает так же, как fread выше. readme в ссылке объясняет разницу между двумя функциями (readr в настоящее время утверждает, что она в 1,5-2 раза медленнее, чем data.table::fread).

  4. read.csv.raw из _ 12_ предоставляет третий вариант для быстрого чтения файлов CSV.

  5. Пытаться хранить как можно больше данных в базах данных, а не в плоских файлах. (Помимо того, что это лучший постоянный носитель, данные передаются в R и из R в двоичном формате, что происходит быстрее.) _ 13_ в sqldf, как описано в ответе JD Long, импортирует данные во временную базу данных SQLite и затем считывает их. в R. См. также: пакет RODBC и обратное зависит от раздела страницы DBI package. MonetDB.R предоставляет вам тип данных, который притворяется data, но на самом деле это MonetDB, повышающий производительность. Импортируйте данные с помощью функции monetdb.read.csv. dplyr позволяет работать напрямую с данными, хранящимися в нескольких типах база данных.

  6. Хранение данных в двоичных форматах также может быть полезно для повышения производительности. Используйте _20 _ / _ 21_ (см. Ниже), h5 или _ 23_ пакеты для формата HDF5 или _24 _ / _ 25_ из _ 26_.


Исходный ответ

Есть несколько простых вещей, которые можно попробовать, независимо от того, используете ли вы read.table или scan.

  1. Установите nrows = количество записей в ваших данных (nmax в scan).

  2. Убедитесь, что comment.char="" отключена интерпретация комментариев.

  3. Явно определите классы каждого столбца, используя colClasses в read.table.

  4. Установка multi.line=FALSE также может улучшить производительность при сканировании.

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

Другой альтернативой является фильтрация ваших данных перед их чтением в R.

Или, если проблема в том, что вам нужно регулярно читать его, используйте эти методы для однократного чтения данных, а затем сохраните фрейм данных как двоичный большой двоичный объект с помощью _ 35_ _ 36_, затем в следующий раз вы сможете получить его быстрее с помощью _ 37_ readRDS.

person Richie Cotton    schedule 13.11.2009
comment
Спасибо за советы, Ричи. Я провел небольшое тестирование, и кажется, что прирост производительности при использовании параметров nrow и colClasses для read.table довольно скромен. Например, чтение таблицы строк размером ~ 7 млн ​​занимает 78 секунд без опций и 67 секунд с опциями. (примечание: таблица имеет 1 символьный столбец, 4 целочисленных столбца, и я читал, используя comment.char = '' и stringsAsFactors = FALSE). Использование save () и load (), когда это возможно, является отличным советом: после сохранения с помощью save () та же таблица загружается всего за 12 секунд. - person eytan; 14.11.2009
comment
Пакет пера имеет новый двоичный формат, который хорошо сочетается с фреймами данных Python pandas. - person rsoren; 30.03.2016
comment
Думаю, может вам нужно еще раз обновить свой пост касаемо пакета feather. Для чтения данных feather намного быстрее, чем fread. Например, для набора данных размером 4 ГБ, который я только что загрузил, read_feather был примерно в 4,5 раза быстрее, чем fread. Для сохранения данных fwrite все еще быстрее. blog.dominodatalab.com/the-r-data-io-shootout - person Z boson; 08.12.2016
comment
Но размеры файлов у пера намного больше, чем у RDS. Я не думаю, что он поддерживает сжатие. Размер файла RDS составляет 216 МБ, а размер файла пера - 4 ГБ. Таким образом, feather быстрее читается, но занимает гораздо больше места для хранения. - person Z boson; 08.12.2016
comment
@Zboson Если вам нужно сохранить фрейм данных в файле, к которому можно получить доступ как из R, так и из Python, то feather - хороший вариант. Если вас интересует только возможность читать ваши данные в R, предпочтительнее rds. - person Richie Cotton; 12.12.2016
comment
Достаточно новый пакет, о котором здесь не упоминалось, - это iotools. Он имеет как возможность быстрого чтения, так и разбиение на части. - person lmo; 29.12.2016
comment
data.table примерно в 30 раз быстрее, чем read.table (не говоря уже о том, что он позволяет избежать избыточного копирования данных) и в 10 раз быстрее для отображения данных в консоли. - person ivan866; 14.02.2020
comment
Об этом упоминалось ниже, но на самом деле vroom не считывает данные сразу. Он читает его по мере того, как он используется, поэтому первоначальный расчет времени вводит в заблуждение. Это может быть оптимальным в некоторых ситуациях, но если вы действительно собираетесь использовать все свои данные, есть веские причины использовать data.table :: fread вместо vroom. - person Michael; 22.07.2021

Вот пример, в котором используется fread из data.table 1.8.7

Примеры взяты со страницы справки на fread, с таймингами на моей Windows XP Core 2 duo E8400.

library(data.table)
# Demo speedup
n=1e6
DT = data.table( a=sample(1:1000,n,replace=TRUE),
                 b=sample(1:1000,n,replace=TRUE),
                 c=rnorm(n),
                 d=sample(c("foo","bar","baz","qux","quux"),n,replace=TRUE),
                 e=rnorm(n),
                 f=sample(1:1000,n,replace=TRUE) )
DT[2,b:=NA_integer_]
DT[4,c:=NA_real_]
DT[3,d:=NA_character_]
DT[5,d:=""]
DT[2,e:=+Inf]
DT[3,e:=-Inf]

стандартная таблица для чтения

write.table(DT,"test.csv",sep=",",row.names=FALSE,quote=FALSE)
cat("File size (MB):",round(file.info("test.csv")$size/1024^2),"\n")    
## File size (MB): 51 

system.time(DF1 <- read.csv("test.csv",stringsAsFactors=FALSE))        
##    user  system elapsed 
##   24.71    0.15   25.42
# second run will be faster
system.time(DF1 <- read.csv("test.csv",stringsAsFactors=FALSE))        
##    user  system elapsed 
##   17.85    0.07   17.98

оптимизированная таблица чтения

system.time(DF2 <- read.table("test.csv",header=TRUE,sep=",",quote="",  
                          stringsAsFactors=FALSE,comment.char="",nrows=n,                   
                          colClasses=c("integer","integer","numeric",                        
                                       "character","numeric","integer")))


##    user  system elapsed 
##   10.20    0.03   10.32

бояться

require(data.table)
system.time(DT <- fread("test.csv"))                                  
 ##    user  system elapsed 
##    3.12    0.01    3.22

sqldf

require(sqldf)

system.time(SQLDF <- read.csv.sql("test.csv",dbname=NULL))             

##    user  system elapsed 
##   12.49    0.09   12.69

# sqldf as on SO

f <- file("test.csv")
system.time(SQLf <- sqldf("select * from f", dbname = tempfile(), file.format = list(header = T, row.names = F)))

##    user  system elapsed 
##   10.21    0.47   10.73

ff / ffdf

 require(ff)

 system.time(FFDF <- read.csv.ffdf(file="test.csv",nrows=n))   
 ##    user  system elapsed 
 ##   10.85    0.10   10.99

В итоге:

##    user  system elapsed  Method
##   24.71    0.15   25.42  read.csv (first time)
##   17.85    0.07   17.98  read.csv (second time)
##   10.20    0.03   10.32  Optimized read.table
##    3.12    0.01    3.22  fread
##   12.49    0.09   12.69  sqldf
##   10.21    0.47   10.73  sqldf on SO
##   10.85    0.10   10.99  ffdf
person mnel    schedule 25.02.2013
comment
Отличный ответ, и сравнительный анализ работает в других контекстах. Просто прочтите файл размером 4 ГБ менее чем за минуту с fread. Пытался прочитать его с помощью базовых функций R, и это заняло около 15 часов. - person Ari B. Friedman; 12.09.2013
comment
мой тест предлагает еще большие преимущества в скорости для read.csv в data.table. обратите внимание, что data.table не является стандартным R, но (к сожалению) его создатели просто приятно разделяют на CRAN. он даже не считается достаточно стандартным, чтобы сделать общий список пакетов R, не говоря уже о замене фреймов данных. у него есть много преимуществ, но есть и некоторые очень противоречивые аспекты. вы можете использовать as.data.frame (fread.csv (test.csv)) с пакетом, чтобы вернуться в мир стандартных фреймов данных R. - person ivo Welch; 17.03.2015
comment
@mnel, не могли бы вы повторно запустить тест и включить readr? - person jangorecki; 09.12.2015
comment
Второй @jangorecki. Кроме того, учитывая, что сейчас у fread есть реальные конкуренты, может быть полезно добавить тесты для оптимизации fread использования - указав colClasses и т. Д. - person MichaelChirico; 07.02.2016
comment
@jangorecji @ MichaelChirico приведенный код полностью воспроизводим, поэтому можно легко смоделировать readr ... повторный запуск кода, на моей машине прошедшее время в два раза быстрее, если не больше, для большинства результатов, хотя я запускаю его по сети (и хорошо обновленные версии, так как прошло какое-то время) ... и с readr я нахожусь на 7 с, но также менее чем на секунду, когда я запускаю второй раз (0,66 с), я подозреваю, что в сети есть какое-то кеширование или какое-то узкое место в сети. fread для самого быстрого решения, показанного здесь, на моей стороне для сравнения составляет 2 с (первый раз работает на 8,69 с) по какой-то причине медленнее) - person R. Prost; 12.03.2018

Сначала я не видел этого вопроса и задал аналогичный вопрос несколько дней спустя. Я собираюсь ответить на свой предыдущий вопрос, но подумал, что добавлю здесь ответ, чтобы объяснить, как я использовал sqldf() для этого.

Было небольшое обсуждение наилучшего способа для импорта 2 ГБ или более текстовых данных во фрейм данных R. Вчера я написал сообщение в блоге об использовании sqldf() для импорта данных в SQLite в качестве промежуточной области, а затем засасывать его из SQLite в R. Это очень хорошо работает для меня. Я смог загрузить 2 ГБ (3 столбца, 40-миллиметровые строки) данных за ‹5 минут. Напротив, команда read.csv выполнялась всю ночь и так и не была завершена.

Вот мой тестовый код:

Настройте тестовые данные:

bigdf <- data.frame(dim=sample(letters, replace=T, 4e7), fact1=rnorm(4e7), fact2=rnorm(4e7, 20, 50))
write.csv(bigdf, 'bigdf.csv', quote = F)

Я перезапустил R перед выполнением следующей процедуры импорта:

library(sqldf)
f <- file("bigdf.csv")
system.time(bigdf <- sqldf("select * from f", dbname = tempfile(), file.format = list(header = T, row.names = F)))

Я позволил следующей строке работать всю ночь, но она так и не завершилась:

system.time(big.df <- read.csv('bigdf.csv'))
person JD Long    schedule 30.11.2009
comment
Привет. Как вы будете использовать его в качестве входных данных для других пакетов, таких как zoo, предназначенных для одновременного использования всех данных? - person skan; 27.03.2013
comment
@skan конечный объект - это фрейм данных. Поэтому вам нужно преобразовать его в объект зоопарка, чтобы использовать с зоопарком. Посмотрите примеры в документации зоопарка для иллюстраций. - person JD Long; 02.04.2013
comment
@JD Long. Привет, проблема в том, что когда вы конвертируете его в объект зоопарка, он пытается уместить его в памяти. Если он слишком большой, возникает ошибка. И если результат объекта zoo (например, агрегация двух серий) также является слишком большим, он также должен быть объектом sql или ff. - person skan; 03.04.2013
comment
Я не знаю, что не так с sqldf. Я создал на диске простой файл размером 1 ГБ (с двумя числовыми столбцами) и использовал DTSQL ‹- read.csv.sql (f2.txt, dbname = tempfile ()), и он пытается загрузить все данные в память. Завтра попробую ff и revoscaler. - person skan; 04.04.2013
comment
Этот метод не обрабатывает данные в кавычках должным образом (например, если все поля заключены в кавычки, а кавычки в полях заключены в двойные кавычки). Документы sqldf затрагивают эту проблему, но, похоже, не предлагают решения. - person hgcrpd; 10.09.2013
comment
@JDLong Я, наверное, проспал это в школе, но что такое 40-миллиметровые ряды? Миллиметр? - person ; 04.01.2016
comment
@ Что такое тысяча, так что миллиметр - это тысяча тысяч или миллион. Мне, наверное, следовало написать это с заглавной буквы как ММ. Но я считаю, что почти любой миллион сокращений может сбить с толку кого-то, если у вас достаточно разнообразная аудитория. Пытаясь быть чрезмерно многословным, я сожалею, что сделал это еще более запутанным! Accountingcoach.com/blog/what-does-m- и-мм-подставка - person JD Long; 04.01.2016
comment
К сожалению, read.cvs.sql не обрабатывает NULL или пустые строки в файле правильно ... - person Chris; 06.04.2016

Как ни странно, в течение многих лет никто не отвечал на нижнюю часть вопроса, даже несмотря на то, что это важный вопрос - data.frames - это просто списки с правильными атрибутами, поэтому, если у вас есть большие данные, вы не хотите использовать as.data.frame или аналогичные для списка . Гораздо быстрее просто "превратить" список во фрейм данных на месте:

attr(df, "row.names") <- .set_row_names(length(df[[1]]))
class(df) <- "data.frame"

Это не делает копию данных, поэтому она выполняется немедленно (в отличие от всех других методов). Предполагается, что вы уже указали names() в списке соответственно.

[Что касается загрузки больших данных в R - лично я выгружаю их по столбцам в двоичные файлы и использую readBin() - это, безусловно, самый быстрый метод (кроме mmapping), и он ограничен только скоростью диска. Анализ файлов ASCII по своей сути медленный (даже в C) по сравнению с двоичными данными.]

person Simon Urbanek    schedule 20.12.2012
comment
Использование tracmem предполагает, что attr<- и class<- делают копии внутри. bit::setattr или data.table::setattr не будет. - person mnel; 20.12.2012
comment
Может, вы использовали неправильный порядок? Если вы используете df=scan(...); names(df)=...; attr...; class..., копии нет - см. tracemem() (проверено в R 2.15.2) - person Simon Urbanek; 20.12.2012
comment
Не могли бы вы подробнее рассказать о том, как выгружать большие данные по столбцам в двоичные файлы? - person dabsingh; 15.09.2016

Ранее это было спросили в R-Help, так что это заслуживает внимания.

Одно из предложений заключалось в том, чтобы использовать readChar(), а затем выполнять строковые манипуляции с результатом с помощью strsplit() и substr(). Вы можете видеть, что логика, задействованная в readChar, намного меньше, чем в read.table.

Я не знаю, является ли здесь проблема с памятью, но вы также можете захотеть чтобы ознакомиться с пакетом HadoopStreaming. Этот использует Hadoop, который представляет собой платформу MapReduce, предназначенную для работы с большими наборами данных. Для этого вы должны использовать функцию hsTableReader. Это пример (но для изучения Hadoop потребуется время):

str <- "key1\t3.9\nkey1\t8.9\nkey1\t1.2\nkey1\t3.9\nkey1\t8.9\nkey1\t1.2\nkey2\t9.9\nkey2\"
cat(str)
cols = list(key='',val=0)
con <- textConnection(str, open = "r")
hsTableReader(con,cols,chunkSize=6,FUN=print,ignoreKey=TRUE)
close(con)

Основная идея здесь - разбить импорт данных на фрагменты. Вы даже можете зайти так далеко, чтобы использовать одну из параллельных сред (например, снег) и запустить импорт данных параллельно, сегментируя файл, но, скорее всего, для больших наборов данных это не поможет, поскольку вы столкнетесь с ограничениями памяти, поэтому map-reduce - лучший подход.

person Shane    schedule 13.11.2009
comment
Я только что провел быстрый тест, и readChar кажется намного быстрее, чем даже readLines по какой-то необъяснимой причине. Однако по сравнению с простым C-тестом он по-прежнему медленный, как грех. В простой задаче чтения 100 мегабайт R примерно в 5-10 раз медленнее, чем C - person Jonathan Chang; 13.11.2009
comment
Не понимаю твоей точки зрения. Задача Hadoop - обрабатывать очень большие данные, о чем и был вопрос. - person Shane; 23.01.2010
comment
Несмотря на название, hsTableReader не имеет ничего общего с Hadoop как таковым, он предназначен для обработки больших данных по частям. Он читает из con, фрагмент строк за раз, и передает каждый фрагмент как data.frame в FUN для обработки. Если ignoreKey = FALSE, выполняется некоторая дополнительная группировка по ключу (запись в первом столбце), что актуально для подходов Map / Reduce. - person DavidR; 05.03.2013
comment
Привет. Как бы вы использовали эти данные Hadoop в качестве входных данных для других пакетов, таких как zoo, предназначенных для одновременного использования со всеми данными? - person skan; 27.03.2013

Альтернативой является использование пакета vroom. Теперь о CRAN. vroom не загружает весь файл, он индексирует, где находится каждая запись, и считывается позже, когда вы ее используете.

Платите только за то, чем пользуетесь.

См. Введение в vroom, Начните работу с vroom и тесты vroom.

Общий обзор заключается в том, что первоначальное чтение огромного файла будет намного быстрее, а последующие модификации данных могут быть немного медленнее. Так что в зависимости от того, что вы используете, это может быть лучший вариант.

См. Упрощенный пример из тестов vroom ниже, ключевые части для см. сверхбыстрое время чтения, но немного упрощает такие операции, как агрегирование и т. д.

package                 read    print   sample   filter  aggregate   total
read.delim              1m      21.5s   1ms      315ms   764ms       1m 22.6s
readr                   33.1s   90ms    2ms      202ms   825ms       34.2s
data.table              15.7s   13ms    1ms      129ms   394ms       16.3s
vroom (altrep) dplyr    1.7s    89ms    1.7s     1.3s    1.9s        6.7s
person Hector Haffenden    schedule 07.05.2019

Я очень быстро читаю данные с помощью нового пакета arrow. Похоже, он находится на довольно ранней стадии.

В частности, я использую столбчатый формат паркет. Это преобразуется обратно в data.frame в R, но вы можете получить еще большее ускорение, если этого не сделаете. Этот формат удобен, так как его можно использовать и из Python.

Мой основной вариант использования для этого - на довольно ограниченном сервере RShiny. По этим причинам я предпочитаю хранить данные прикрепленными к приложениям (т.е. вне SQL), и поэтому требую небольшой размер файла, а также скорость.

В этой связанной статье представлен сравнительный анализ и хороший обзор. Ниже я привел несколько интересных моментов.

https://ursalabs.org/blog/2019-10-columnar-perf/

Размер файла

То есть файл Parquet вдвое меньше даже сжатого с помощью gzip CSV. Одна из причин того, что файл Parquet такой маленький, - это кодирование по словарю (также называемое «сжатием словаря»). Сжатие словаря может дать значительно лучшее сжатие, чем использование компрессора байтов общего назначения, такого как LZ4 или ZSTD (которые используются в формате FST). Parquet был разработан для создания очень маленьких файлов, которые быстро читаются.

Скорость чтения

При управлении по типу вывода (например, при сравнении всех выходных данных R data.frame друг с другом) мы видим, что производительность Parquet, Feather и FST находится в относительно небольшом диапазоне друг от друга. То же самое и с выводами pandas.DataFrame. data.table :: fread впечатляюще конкурирует с размером файла 1,5 ГБ, но отстает от других на 2,5 ГБ CSV.


Независимый тест

Я провел несколько независимых сравнительных тестов на смоделированном наборе данных из 1000000 строк. В основном я перетасовал кучу вещей, чтобы попытаться оспорить сжатие. Также я добавил короткое текстовое поле со случайными словами и двумя смоделированными факторами.

Данные

library(dplyr)
library(tibble)
library(OpenRepGrid)

n <- 1000000

set.seed(1234)
some_levels1 <- sapply(1:10, function(x) paste(LETTERS[sample(1:26, size = sample(3:8, 1), replace = TRUE)], collapse = ""))
some_levels2 <- sapply(1:65, function(x) paste(LETTERS[sample(1:26, size = sample(5:16, 1), replace = TRUE)], collapse = ""))


test_data <- mtcars %>%
  rownames_to_column() %>%
  sample_n(n, replace = TRUE) %>%
  mutate_all(~ sample(., length(.))) %>%
  mutate(factor1 = sample(some_levels1, n, replace = TRUE),
         factor2 = sample(some_levels2, n, replace = TRUE),
         text = randomSentences(n, sample(3:8, n, replace = TRUE))
         )

Прочти и напиши

Запись данных проста.

library(arrow)

write_parquet(test_data , "test_data.parquet")

# you can also mess with the compression
write_parquet(test_data, "test_data2.parquet", compress = "gzip", compression_level = 9)

Считывать данные также легко.

read_parquet("test_data.parquet")

# this option will result in lightning fast reads, but in a different format.
read_parquet("test_data2.parquet", as_data_frame = FALSE)

Я протестировал чтение этих данных с несколькими конкурирующими вариантами и получил несколько иные результаты, чем в статье выше, чего и следовало ожидать.

сравнительный анализ

Этот файл далеко не такой большой, как статья о тесте, так что, возможно, в этом разница.

Тесты

  • rds: test_data.rds (20,3 МБ)
  • parquet2_native: (14,9 МБ с более высоким сжатием и as_data_frame = FALSE)
  • parquet2: test_data2.parquet (14,9 МБ с более высоким сжатием)
  • паркет: test_data.parquet (40,7 МБ)
  • fst2: test_data2.fst (27,9 МБ с более высоким сжатием)
  • fst: test_data.fst (76,8 МБ)
  • fread2: test_data.csv.gz (23,6 МБ)
  • fread: test_data.csv (98,7 МБ)
  • Pen_arrow: test_data.feather (157,2 МБ при чтении с arrow)
  • перо: test_data.feather (157,2 МБ при чтении с feather)

Наблюдения

Для этого конкретного файла fread действительно работает очень быстро. Мне нравится небольшой размер файла из теста parquet2 с высокой степенью сжатия. Я могу потратить время на работу с собственным форматом данных, а не data.frame, если мне действительно нужно ускорение.

Здесь fst тоже отличный выбор. Я бы использовал либо сильно сжатый fst формат, либо сильно сжатый parquet, в зависимости от того, нужен ли мне компромисс между скоростью или размером файла.

person Adam    schedule 12.11.2019

Стоит упомянуть несколько дополнительных моментов. Если у вас очень большой файл, вы можете на лету вычислить количество строк (если нет заголовка), используя (где bedGraph - имя вашего файла в вашем рабочем каталоге):

>numRow=as.integer(system(paste("wc -l", bedGraph, "| sed 's/[^0-9.]*\\([0-9.]*\\).*/\\1/'"), intern=T))

Затем вы можете использовать это в read.csv, read.table ...

>system.time((BG=read.table(bedGraph, nrows=numRow, col.names=c('chr', 'start', 'end', 'score'),colClasses=c('character', rep('integer',3)))))
   user  system elapsed 
 25.877   0.887  26.752 
>object.size(BG)
203949432 bytes
person Stephen Henderson    schedule 28.11.2013

Часто я думаю, что хранить большие базы данных внутри базы данных (например, Postgres) - это просто хорошая практика. Я не использую ничего слишком большого, чем (nrow * ncol) ncell = 10M, что довольно мало; но я часто обнаруживаю, что хочу, чтобы R создавал и сохранял графики с интенсивным использованием памяти только во время запроса из нескольких баз данных. В будущем ноутбуков с 32 ГБ памяти исчезнут некоторые из этих проблем с памятью. Но привлекательность использования базы данных для хранения данных и последующего использования памяти R для результирующих результатов запроса и графиков по-прежнему может быть полезной. Некоторые преимущества:

(1) Данные остаются загруженными в вашу базу данных. Вы просто повторно подключаетесь в pgadmin к нужным базам данных, когда снова включаете свой ноутбук.

(2) Это правда, что R может выполнять гораздо больше изящных статистических и графических операций, чем SQL. Но я думаю, что SQL лучше разработан для запроса больших объемов данных, чем R.

# Looking at Voter/Registrant Age by Decade

library(RPostgreSQL);library(lattice)

con <- dbConnect(PostgreSQL(), user= "postgres", password="password",
                 port="2345", host="localhost", dbname="WC2014_08_01_2014")

Decade_BD_1980_42 <- dbGetQuery(con,"Select PrecinctID,Count(PrecinctID),extract(DECADE from Birthdate) from voterdb where extract(DECADE from Birthdate)::numeric > 198 and PrecinctID in (Select * from LD42) Group By PrecinctID,date_part Order by Count DESC;")

Decade_RD_1980_42 <- dbGetQuery(con,"Select PrecinctID,Count(PrecinctID),extract(DECADE from RegistrationDate) from voterdb where extract(DECADE from RegistrationDate)::numeric > 198 and PrecinctID in (Select * from LD42) Group By PrecinctID,date_part Order by Count DESC;")

with(Decade_BD_1980_42,(barchart(~count | as.factor(precinctid))));
mtext("42LD Birthdays later than 1980 by Precinct",side=1,line=0)

with(Decade_RD_1980_42,(barchart(~count | as.factor(precinctid))));
mtext("42LD Registration Dates later than 1980 by Precinct",side=1,line=0)
person rferrisx    schedule 22.08.2014

Мне кажется, что вместо обычной read.table более быстрая функция - fread. Указание дополнительных атрибутов, таких как выбор только необходимых столбцов, указание классов и строк в качестве факторов, сократит время, необходимое для импорта файла.

data_frame <- fread("filename.csv",sep=",",header=FALSE,stringsAsFactors=FALSE,select=c(1,4,5,6,7),colClasses=c("as.numeric","as.character","as.numeric","as.Date","as.Factor"))
person Aayush Agrawal    schedule 18.04.2015

Я перепробовал все вышеперечисленное, и [readr] [1] справился лучше всех. У меня всего 8гб оперативной памяти

Цикл на 20 файлов по 5гб, 7 столбцов:

read_fwf(arquivos[i],col_types = "ccccccc",fwf_cols(cnpj = c(4,17), nome = c(19,168), cpf = c(169,183), fantasia = c(169,223), sit.cadastral = c(224,225), dt.sitcadastral = c(226,233), cnae = c(376,382)))
person Bruno Gomes    schedule 29.12.2019