Швидке читання дуже великих таблиць як кадрів даних


503

У мене дуже великі таблиці (30 мільйонів рядків), які я хотів би завантажувати, як фрейми даних у Р. 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))))

Чи є кращий спосіб зробити це? Або цілком можливо зовсім інший підхід до проблеми?

Відповіді:


425

Оновлення, через кілька років

Ця відповідь стара, і R пішла далі. Налаштування read.tableбігати трохи швидше мало корисної користі. Ваші варіанти:

  1. Використання vroomз пакета tidyverse vroomдля імпорту даних із файлів, обмежених файлами csv / tab, безпосередньо в таблицю R.

  2. Використання freadв data.tableдля імпорту даних з CSV / роздільниками табуляції файлів безпосередньо в Р. знайомства відповідь mnel в .

  3. Використання read_tableв readr(на CRAN з квітня 2015 року). Це працює так, як freadвище. Рідй на засланні пояснює різницю між цими двома функціями ( в readrданий час стверджує, що «1.5-2x повільніше» , ніж data.table::fread).

  4. read.csv.rawз iotoolsнадає третій варіант для швидкого читання файлів CSV.

  5. Намагання зберігати якомога більше даних у базах даних, а не в плоских файлах. (Окрім того, що є кращим постійним носієм зберігання, дані передаються до та з R у двійковому форматі, який швидше.) read.csv.sqlУ sqldfпакеті, як описано у відповіді JD Лонга , імпортуються дані у тимчасову базу даних SQLite, а потім зчитуються в Р. Див. також: RODBCпакет і зворотній залежно від розділу сторінки DBIпакета . MonetDB.Rдає вам тип даних, який видається фреймом даних, але справді є MonetDB під ним, підвищуючи продуктивність. Імпорт даних із його monetdb.read.csvфункцією. dplyrдозволяє безпосередньо працювати з даними, що зберігаються в декількох типах баз даних.

  6. Збереження даних у двійкових форматах також може бути корисним для підвищення продуктивності. Використовуйте saveRDS/ readRDS(див. Нижче), h5або rhdf5пакети для формату HDF5 або write_fst/ read_fstз fstпакета.


Оригінальна відповідь

Спробуйте скористатись декількома простими речами, використовуючи читання та сканування.

  1. Встановити nrows= кількість записів у ваших даних ( nmaxв scan).

  2. Переконайтесь, comment.char=""щоби вимкнути інтерпретацію коментарів.

  3. Явна визначити класи кожного стовпчика , використовуючи colClassesв read.table.

  4. Налаштування multi.line=FALSEтакож можуть покращити продуктивність при скануванні.

Якщо жодна з цих речей не працює, то використовуйте один із пакетів профілювання, щоб визначити, які рядки уповільнюють ситуацію. Можливо, ви можете написати скорочену версію на read.tableоснові результатів.

Інша альтернатива - це фільтрувати ваші дані, перш ніж прочитати їх у Р.

Або якщо проблема полягає в тому, що вам доводиться регулярно її читати, використовуйте ці методи, щоб прочитати дані один раз, а потім збережіть кадр даних у вигляді двійкового блоку з save saveRDS, то наступного разу ви зможете швидше її отримати load readRDS.


4
Дякую за поради Річі. Я трохи тестував, і, схоже, підвищення продуктивності використання параметрів nrow та colClasses для read.table досить скромне. Наприклад, для читання таблиці 7 рядків ~ 7М займає 78s без варіантів, і 67s з параметрами. (зауважте: таблиця містить 1 символьний стовпець, 4 цілі стовпці, і я читаю, використовуючи comment.char = '' та stringsAsFactors = FALSE). Використання save () та load (), коли це можливо, є чудовим підказом - коли він зберігається разом із save (), для завантаження цієї ж таблиці потрібно лише 12 секунд.
Ейтан

2
Пакет "перо" має новий двійковий формат, який чудово грає з кадрами даних панди Python
rsoren

4
Я думаю, можливо, вам потрібно буде оновити свою посаду ще раз щодо пакета feather. Для читання даних featherнабагато швидше, ніж fread. Наприклад, щойно завантажений я набір даних 4 Гб read_featherбув приблизно в 4,5 рази швидшим, ніж fread. Збереження даних fwriteвсе-таки швидше. blog.dominodatalab.com/the-r-data-io-shootout
Z boson

2
Але розміри файлів набагато більші для пера, ніж для RDS. Я не думаю, що він підтримує стиснення. Файл RDS становить 216 МБ, а файл пір'я - 4 Гб. Це featherшвидше для читання, але воно використовує набагато більше місця для зберігання.
Z boson

@Zboson Якщо вам потрібно зберегти кадр даних у файлі, до якого можна отримати доступ і з R, і з Python, тоді featherце хороший варіант. Якщо ви дбаєте лише про те, щоб мати змогу читати ваші дані на R, rdsкраще.
Річі Коттон

279

Ось приклад, який використовується freadз data.table1.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

43
Відмінна відповідь, і тест-бенчмаркінг має місце і в інших контекстах. Просто прочитайте у файлі об'ємом 4 ГБ, а також за хвилину fread. Спробував прочитати його з базовими функціями R, і це зайняло близько 15 годин.
Арі Б. Фрідман

1
мій показник пропонує ще більші переваги швидкості для read.csv у data.table. зауважте, що data.table не є стандартним R, але (на жаль) "просто" добре поділився його творцями на CRAN. це навіть не вважається достатньо стандартним для складання загального списку пакетів R, тим більше менш кваліфікується як заміна кадрів даних. він має багато переваг, але також і дуже протиконкурентні аспекти. ви можете використовувати as.data.frame (fread.csv ("test.csv")) з пакетом, щоб повернутися в стандартний світ кадру даних R.
ivo Welch

3
@mnel, чи можете ви повторно запустити показник та включити його readr?
jangorecki

2
Другий @jangorecki. Крім того, з огляду на те, що зараз freadє кілька реальних конкурентів, може бути корисно додати орієнтири для оптимізованого freadвикористання - уточнення colClassesтощо
MichaelChirico

1
@jangorecji @ MichaelChirico наведений код є повністю відтворюваним, тому він прямо вперед змоделює зчитувач ... повторний код, на моїй машині час минув удвічі швидше, якщо не більше для більшості результатів, навіть якщо я запускаю його по мережі (і добре оновлені версії, як це вже зараз) ... і з Reader я в 7s, але також за секунду, коли я запускаю вдруге (0.66s), я підозрюю, що в мережі є якесь кешування або якась шийка пляшки. фрейд для найшвидшого рішення, показаного тут, знаходиться в 2 години на моєму боці для порівняння (перший раз працює в 8.69 с) чомусь повільніше)
Р. Прост,

249

Я не бачив цього запитання спочатку, а через кілька днів подібне запитання я не задавав. Я збираюся зняти своє попереднє запитання, але я подумав, що тут додам відповідь, щоб пояснити, як я 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'))

1
Привіт. Як ви використовуєте його як вхід для інших пакетів, таких як зоопарк, призначених для одночасного використання з усіма даними?
скан

@skan кінцевим об’єктом є кадр даних. Тому вам доведеться перетворити його в зоопарк, щоб використовувати його з зоопарком. Подивіться приклади в документах зоопарку для ілюстрацій.
JD Long

@JD Лонг. Привіт, проблема полягає в тому, що коли ви перетворюєте його в зоопарк, він намагається помістити його в пам'яті. Якщо вона занадто велика, це створює помилку. І якщо результат об’єкта зоопарку (наприклад, агрегація з двох серій) також занадто, він також повинен бути об’єктом sql або ff.
скан

Я не знаю, що не так з sqldf. Я створив простий файл на 1 Гб на диску (з 2 числовими стовпцями) і використав DTSQL <- read.csv.sql ("f2.txt", dbname = tempfile ()) і він намагається завантажити всі дані в пам'ять. Завтра я спробую ff та revoscaler замість цього.
скан

1
@ Що m - тисяча, то мм - це тисяча тисяч, або мільйон. Я, мабуть, мав би використати великі літери як ММ Але я вважаю, що майже будь-який мільйон абревіатура може когось бентежити, якщо у вас достатньо різноманітна аудиторія. У своїй спробі бути надмірно багатослівним, мені шкода, що я зробив це більш заплутаним! accountcoach.com/blog/what-does-m-and-mm-stand-for
JD Довгий

73

Як не дивно, ніхто не відповідав нижній частині питання роками, хоча це важливо - data.frameце просто списки з правильними атрибутами, тому, якщо у вас є великі дані, ви не хочете використовувати as.data.frameабо подібні для списку. Набагато швидше просто "перетворити" список на кадр даних на місці:

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

Це не робить копії даних, тому вона негайна (на відміну від усіх інших методів). Це передбачає, що ви вже встановлені names()у списку відповідно.

[Що стосується завантаження великих даних у R - особисто я скидаю їх за стовпцями у бінарні файли та використовую readBin()- це, безумовно, найшвидший метод (крім mmapping) і обмежений лише швидкістю диска. Розбір файлів ASCII за своєю суттю повільний (навіть у С) порівняно з двійковими даними.]


6
Використання tracmemпропонує це зробити attr<-і class<-зробити копії всередині. bit::setattrчи data.table::setattrне буде.
квітня 1212

6
Можливо, ви використали неправильний наказ? Немає копії, якщо ви використовуєте df=scan(...); names(df)=...; attr...; class...- див. tracemem()(Перевірено в R 2.15.2)
Simon Urbanek

3
Чи можете ви детальніше пояснити, як ви скидаєте великі дані за стовпцями у бінарні файли?
Дабсінг

32

Про це раніше запитували в R-Help , тому це варто переглянути.

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

Я не знаю, чи пам'ять тут є проблемою, але ви також можете поглянути на пакет 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)

Основна ідея тут - розбити імпорт даних на шматки. Ви навіть можете зайти так далеко, щоб скористатися однією з паралельних фреймів (наприклад, сніг) та запустити імпорт даних паралельно, сегментуючи файл, але, швидше за все, для великих наборів даних, які не допоможуть, оскільки у вас виникнуть обмеження в пам'яті, саме тому зменшення карт - кращий підхід.


Я просто зробив швидкий тест і readChar здається набагато швидшим, ніж навіть readLines з якихось незрозумілих причин. Однак він все ще повільний як гріх порівняно з простим тестом на С. При простому завданні читання 100 мег R на 5 - 10 разів повільніше, ніж C
Джонатан Чанг

1
Не розумію вашої точки зору. Справа Hadoop - обробляти дуже великі дані, саме про це йшлося.
Шейн

1
Незважаючи на назву, hsTableReader не має нічого спільного з Hadoop як такий, це для обробки великих даних у шматках. Він читає з con, шматок рядків за один раз і передає кожен фрагмент як кадр даних.FUN для обробки. З ignoreKey = FALSE, він робить додаткову групування за клавішами (запис у першому стовпці), що стосується підходів Map / Reduce.
DavidR

Привіт. Як би ви використовували ці дані Hadoop як вхідні дані для інших пакетів, таких як зоопарк, призначених для одночасного використання з усіма даними?
скан

10

Альтернативою є використання 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

5

Незначні додаткові моменти, які варто згадати. Якщо у вас дуже великий файл, ви можете на ходу обчислити кількість рядків (якщо немає заголовка), використовуючи (де 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

4

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

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

(2) Це правда, що R може виконувати набагато витонченіші статистичні та графічні операції, ніж SQL. Але я думаю, що SQL краще розроблений для запиту великих обсягів даних, ніж Р.

# 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)

3

Я дуже швидко читаю дані, використовуючи новий arrowпакет. Здається, він знаходиться на досить ранній стадії.

Зокрема, я використовую стовпчастий формат паркету . Це перетворюється назад в a data.frameв R, але ви можете отримати ще більш глибокі прискорення, якщо цього не зробите. Цей формат зручний, оскільки його можна використовувати і з Python.

Головний мій приклад для цього - на досить стриманому сервері RShiny. З цих причин я вважаю за краще зберігати дані, додані до Додатків (тобто, поза SQL), а тому вимагаю невеликого розміру файлу, а також швидкості.

Ця пов’язана стаття забезпечує тестування та хороший огляд. Нижче я наводив кілька цікавих моментів.

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

Розмір файлу

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

Швидкість читання

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


Незалежний тест

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

Дані

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)
  • паркет2 : 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 МБ)
  • feather_arrow: test_data.feather (157,2 Мб читати разом arrow)
  • перо: test_data.feather (157,2 Мб читати з feather)

Спостереження

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

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


0

Замість звичайного 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"))

0

Я спробував усе вище, і [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)))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.