Cepat membaca tabel yang sangat besar sebagai kerangka data

504

Saya memiliki tabel yang sangat besar (30 juta baris) yang ingin saya muat sebagai dataframe di R. read.table()memiliki banyak fitur yang mudah, tetapi sepertinya ada banyak logika dalam implementasi yang akan memperlambat segalanya. Dalam kasus saya, saya berasumsi saya tahu jenis kolom sebelumnya, tabel tidak berisi judul kolom atau nama baris, dan tidak memiliki karakter patologis yang harus saya khawatirkan.

Saya tahu bahwa membaca dalam tabel sebagai daftar menggunakan scan()bisa sangat cepat, misalnya:

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

Tetapi beberapa upaya saya untuk mengonversikan ini ke dataframe nampak mengurangi kinerja di atas dengan faktor 6:

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

Apakah ada cara yang lebih baik untuk melakukan ini? Atau mungkin pendekatan yang sangat berbeda untuk masalah ini?

eytan
sumber

Jawaban:

426

Pembaruan, beberapa tahun kemudian

Jawaban ini sudah tua, dan R telah pindah. Tweaking read.tableuntuk berlari sedikit lebih cepat memiliki sedikit manfaat. Pilihan Anda adalah:

  1. Menggunakan vroomdari paket rapi vroomuntuk mengimpor data dari file csv / tab-delimited langsung ke R tibble.

  2. Menggunakan freaddi data.tableuntuk mengimpor data dari csv / file tab-delimited langsung ke R. See jawaban mnel ini .

  3. Menggunakan read_tabledalam readr(pada CRAN dari April 2015). Ini berfungsi seperti di freadatas. The readme di link menjelaskan perbedaan antara dua fungsi ( readrsaat ini mengklaim sebagai "1.5-2x lebih lambat" dari data.table::fread).

  4. read.csv.rawfrom iotoolsmenyediakan opsi ketiga untuk membaca file CSV dengan cepat.

  5. Mencoba menyimpan data sebanyak mungkin di basis data alih-alih file rata. (Selain sebagai media penyimpanan permanen yang lebih baik, data diteruskan ke dan dari R dalam format biner, yang lebih cepat.) read.csv.sqlDalam sqldfpaket, seperti yang dijelaskan dalam jawaban JD Long , mengimpor data ke dalam basis data SQLite sementara dan kemudian membacanya ke dalam R. Lihat juga: RODBCpaket, dan kebalikannya bergantung pada halaman DBIpaket . MonetDB.Rmemberi Anda tipe data yang berpura-pura menjadi bingkai data tetapi sebenarnya adalah MonetDB di bawahnya, yang meningkatkan kinerja. Impor data dengan monetdb.read.csvfungsinya. dplyrmemungkinkan Anda untuk bekerja secara langsung dengan data yang disimpan dalam beberapa jenis database.

  6. Menyimpan data dalam format biner juga dapat berguna untuk meningkatkan kinerja. Gunakan saveRDS/ readRDS(lihat di bawah), h5atau rhdf5paket untuk format HDF5, atau write_fst/ read_fstdari fstpaket.


Jawaban asli

Ada beberapa hal sederhana untuk dicoba, apakah Anda menggunakan read.table atau scan.

  1. Set nrows= jumlah rekaman dalam data Anda ( nmaxdalam scan).

  2. Pastikan comment.char=""untuk mematikan interpretasi komentar.

  3. Tetapkan secara eksplisit kelas-kelas dari setiap kolom yang digunakan colClassesdi read.table.

  4. Pengaturan multi.line=FALSEjuga dapat meningkatkan kinerja dalam pemindaian.

Jika tidak ada yang berfungsi, gunakan salah satu paket profil untuk menentukan baris mana yang memperlambat segalanya. Mungkin Anda dapat menulis versi pengurangan read.tableberdasarkan hasil.

Alternatif lain adalah memfilter data Anda sebelum membacanya ke R.

Atau, jika masalahnya adalah Anda harus membacanya secara teratur, maka gunakan metode ini untuk membaca data sekaligus, kemudian simpan bingkai data sebagai gumpalan biner dengan save saveRDS, maka lain kali Anda dapat mengambilnya dengan lebih cepat load readRDS.

Richie Cotton
sumber
4
Terima kasih atas tipsnya Richie. Saya melakukan sedikit pengujian, dan tampaknya kinerja meningkat dengan menggunakan opsi nrow dan colClasses untuk read.table yang cukup sederhana. Sebagai contoh, membaca tabel baris 7M membutuhkan waktu 78 tanpa opsi, dan 67 dengan opsi. (catatan: tabel memiliki 1 kolom karakter, 4 kolom integer, dan saya baca menggunakan comment.char = '' dan stringsAsFactors = FALSE). Menggunakan save () dan memuat () bila memungkinkan adalah tip yang bagus - setelah disimpan dengan save (), tabel yang sama hanya membutuhkan 12 detik untuk memuat.
eytan
2
Paket "feather" memiliki format biner baru yang cocok dengan bingkai data panda Python
rsoren
4
Saya pikir mungkin Anda perlu memperbarui posting Anda lagi sehubungan dengan paket feather. Untuk membaca data featherjauh lebih cepat daripada fread. Sebagai contoh pada dataset 4GB yang baru saya muat read_feathersekitar 4,5 kali lebih cepat daripada fread. Untuk menyimpan data fwritemasih lebih cepat. blog.dominodatalab.com/the-r-data-io-shootout
Z boson
2
Tetapi ukuran file jauh lebih besar untuk bulu daripada dengan RDS. Saya tidak berpikir itu mendukung kompresi. File RDS adalah 216 MB dan file bulu 4GB. Jadi featherlebih cepat untuk membaca tetapi menggunakan lebih banyak ruang penyimpanan.
Z boson
@Zboson Jika Anda perlu menyimpan bingkai data dalam file yang dapat diakses dari R dan Python, maka itu featheradalah opsi yang baik. Jika Anda hanya peduli untuk dapat membaca data Anda dalam R, rdslebih disukai.
Richie Cotton
279

Berikut adalah contoh yang memanfaatkan freaddari data.table1.8.7

Contohnya datang dari halaman bantuan ke fread, dengan timing di windows XP Core 2 duo E8400 saya.

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]

tabel read.tabel standar

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

baca tabel dioptimalkan

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

ketakutan

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

Singkatnya:

##    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
mnel
sumber
43
Jawaban yang bagus, dan tolok ukur berlaku dalam konteks lain. Cukup baca dalam file 4GB dalam waktu kurang dari satu menit fread. Sudah mencoba membacanya dengan fungsi dasar R dan butuh sekitar 15 jam.
Ari B. Friedman
1
tolok ukur saya menyarankan keuntungan kecepatan lebih besar untuk read.csv di data.table. perhatikan bahwa data.tabel bukan standar R, tetapi (sayangnya) "hanya" dibagikan dengan baik oleh pembuatnya di CRAN. bahkan tidak dianggap cukup standar untuk membuat daftar paket R umum, apalagi memenuhi syarat sebagai pengganti bingkai data. ia memiliki banyak keuntungan, tetapi juga beberapa aspek yang sangat berlawanan dengan intuisi. Anda mungkin ingin menggunakan as.data.frame (fread.csv ("test.csv")) dengan paket untuk kembali ke dunia bingkai data R standar.
ivo Welch
3
@mnel, bisakah Anda menjalankan kembali patokan dan memasukkan readr?
jangorecki
2
@Jangorecki kedua. Juga, mengingat freadmemiliki beberapa pesaing nyata sekarang, dapat bermanfaat untuk menambah tolok ukur untuk freadpenggunaan yang dioptimalkan - menentukan colClasses, dll.
MichaelChirico
1
@jangorecji @ MichaelChirico kode yang diberikan sepenuhnya dapat direproduksi sehingga sangat mudah untuk mensimulasikan readr ... jalankan kembali kode, pada mesin saya waktu berlalu dua kali lebih cepat jika tidak lebih untuk sebagian besar hasil walaupun saya menjalankannya melalui jaringan (dan versi baik diperbarui karena beberapa waktu sekarang) ... dan dengan readr saya di 7s tetapi juga di bawah satu detik ketika saya menjalankan kedua kalinya (0,66s), saya curiga ada beberapa caching atau leher botol dalam jaringan. takut untuk solusi tercepat yang ditunjukkan di sini adalah 2s di pihak saya untuk perbandingan (pertama kali berjalan pada 8,69) untuk beberapa alasan lebih lambat)
R. Prost
249

Awalnya saya tidak melihat pertanyaan ini dan mengajukan pertanyaan serupa beberapa hari kemudian. Saya akan menjawab pertanyaan saya sebelumnya, tetapi saya pikir saya akan menambahkan jawaban di sini untuk menjelaskan bagaimana saya sqldf()melakukan ini.

Ada sedikit diskusi tentang cara terbaik untuk mengimpor 2GB atau lebih data teks ke dalam bingkai data R. Kemarin saya menulis posting blog tentang menggunakan sqldf()untuk mengimpor data ke SQLite sebagai area pementasan, dan kemudian mengisapnya dari SQLite ke R. Ini bekerja sangat baik untuk saya. Saya dapat menarik 2GB (3 kolom, baris 40mm) data dalam <5 menit. Sebaliknya, read.csvperintah itu berjalan sepanjang malam dan tidak pernah selesai.

Ini kode pengujian saya:

Siapkan data uji:

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

Saya memulai ulang R sebelum menjalankan rutin impor berikut:

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

Saya membiarkan baris berikut berjalan sepanjang malam tetapi tidak pernah selesai:

system.time(big.df <- read.csv('bigdf.csv'))
JD Long
sumber
1
Hai. Bagaimana Anda menggunakannya sebagai input untuk paket lain seperti kebun binatang, yang dirancang untuk digunakan dengan semua data secara bersamaan?
skan
@skan objek akhir adalah bingkai data. Jadi, Anda harus mengubahnya menjadi objek kebun binatang untuk menggunakannya dengan kebun binatang. Lihatlah contoh-contoh dalam dokumentasi kebun binatang untuk ilustrasi.
JD Long
@ JD Long. Hai, masalahnya adalah ketika Anda mengubahnya menjadi objek kebun binatang, ia mencoba untuk memasangnya di memori. Jika terlalu besar menghasilkan kesalahan. Dan jika hasil dari objek kebun binatang (misalnya agregasi dari dua seri) juga akan perlu menjadi objek sql atau ff juga.
skan
Saya tidak tahu apa yang salah dengan sqldf. Saya telah membuat file 1GB sederhana pada disk (dengan 2 kolom numerik) dan menggunakan DTSQL <- read.csv.sql ("f2.txt", dbname = tempfile ()) dan mencoba memuat seluruh data pada memori. Besok saya akan mencoba ff dan revoscaler sebagai gantinya.
skan
1
@ apa m adalah seribu jadi mm adalah seribu ribu, atau juta. Saya mungkin seharusnya menggunakan huruf kapital sebagai MM. Tetapi saya menemukan bahwa hampir satu juta singkatan dapat membingungkan seseorang jika Anda memiliki audiens yang cukup beragam. Dalam upaya saya untuk terlalu bertele-tele, saya minta maaf saya membuatnya lebih membingungkan! accountingcoach.com/blog/what-does-m-and-mm-stand-for
JD Long
73

Anehnya, tidak ada yang menjawab bagian bawah pertanyaan selama bertahun-tahun meskipun ini adalah yang penting - data.framehanya daftar dengan atribut yang tepat, jadi jika Anda memiliki data besar Anda tidak ingin menggunakan as.data.frameatau serupa untuk daftar. Jauh lebih cepat untuk "mengubah" daftar menjadi bingkai data di tempat:

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

Ini tidak membuat salinan data sehingga langsung (tidak seperti semua metode lain). Diasumsikan bahwa Anda telah menetapkan names()pada daftar yang sesuai.

[Adapun untuk memuat data besar ke R - secara pribadi, saya membuangnya dengan kolom ke file biner dan menggunakan readBin()- yang sejauh ini merupakan metode tercepat (selain mmapping) dan hanya dibatasi oleh kecepatan disk. Parsing file ASCII secara inheren lambat (bahkan dalam C) dibandingkan dengan data biner.]

Simon Urbanek
sumber
6
Menggunakan tracmemmenyarankan itu attr<-dan class<-membuat salinan secara internal. bit::setattratau data.table::setattrtidak.
mnel
6
Mungkin Anda menggunakan urutan yang salah? Tidak ada salinan jika Anda menggunakan df=scan(...); names(df)=...; attr...; class...- lihat tracemem()(diuji dalam R 2.15.2)
Simon Urbanek
3
Bisakah Anda menguraikan cara Anda membuang data besar dengan kolom ke file biner?
dabsingh
32

Ini sebelumnya ditanyakan pada R-Help , jadi itu layak ditinjau.

Satu saran ada untuk menggunakan readChar()dan kemudian melakukan manipulasi string pada hasil dengan strsplit()dan substr(). Anda dapat melihat logika yang terlibat dalam readChar jauh lebih sedikit daripada read.table.

Saya tidak tahu apakah memori menjadi masalah di sini, tetapi Anda mungkin juga ingin melihat pada paket HadoopStreaming . Ini menggunakan Hadoop , yang merupakan kerangka kerja MapReduce yang dirancang untuk menangani set data besar. Untuk ini, Anda akan menggunakan fungsi hsTableReader. Ini adalah contoh (tetapi memiliki kurva belajar untuk mempelajari 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)

Ide dasar di sini adalah memecah impor data menjadi potongan-potongan. Anda bahkan dapat melangkah lebih jauh dengan menggunakan salah satu kerangka kerja paralel (misalnya salju) dan menjalankan impor data secara paralel dengan mensegmentasi file, tetapi kemungkinan besar untuk kumpulan data besar yang tidak akan membantu karena Anda akan mengalami kendala memori, itulah sebabnya pengurangan peta adalah pendekatan yang lebih baik.

Shane
sumber
Saya baru saja melakukan tes cepat dan readChar tampaknya jauh lebih cepat daripada readLines untuk beberapa alasan yang tidak dapat dijelaskan. Namun, masih lambat sebagai dosa dibandingkan dengan tes C sederhana. Pada tugas sederhana membaca 100 MB, R adalah sekitar 5 - 10x lebih lambat daripada C
Jonathan Chang
1
Tidak mengerti maksud Anda. Maksud dari Hadoop adalah untuk menangani data yang sangat besar, yang menjadi pertanyaannya.
Shane
1
Terlepas dari namanya, hsTableReader tidak ada hubungannya dengan Hadoop per se, itu untuk memproses data berukuran besar. Bunyinya dari con, sepotong baris pada satu waktu, dan melewati setiap potongan sebagai data.frame ke FUN untuk diproses. Dengan ignKey = FALSE, ia melakukan pengelompokan tambahan dengan kunci (entri di kolom pertama), yang relevan dengan pendekatan Peta / Kurangi.
DavidR
Hai. Bagaimana Anda menggunakan data Hadoop ini sebagai input untuk paket lain seperti kebun binatang, yang dirancang untuk digunakan dengan semua data secara bersamaan?
skan
10

Alternatifnya adalah menggunakan vroompaket. Sekarang di CRAN. vroomtidak memuat seluruh file, itu mengindeks tempat setiap catatan berada, dan dibaca nanti saat Anda menggunakannya.

Hanya bayar untuk apa yang Anda gunakan.

Lihat Pengantar vroom , Mulailah dengan vroom dan tolok ukur vroom .

Gambaran dasar adalah bahwa pembacaan awal file besar, akan jauh lebih cepat, dan modifikasi selanjutnya pada data mungkin sedikit lebih lambat. Jadi tergantung pada apa yang Anda gunakan, itu bisa menjadi pilihan terbaik.

Lihat contoh sederhana dari tolok ukur vroom di bawah ini, bagian utama yang harus dilihat adalah waktu baca super cepat, tetapi operasi yang sedikit menabur seperti agregat dll.

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
Hector Haffenden
sumber
5

Poin tambahan kecil yang layak disebut. Jika Anda memiliki file yang sangat besar Anda dapat dengan cepat menghitung jumlah baris (jika tidak ada header) menggunakan (di mana bedGraphnama file Anda di direktori kerja Anda):

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

Anda kemudian dapat menggunakannya di 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
Stephen Henderson
sumber
4

Sering kali saya pikir itu hanya praktik yang baik untuk menyimpan basis data yang lebih besar di dalam basis data (misalnya Postgres). Saya tidak menggunakan sesuatu yang terlalu besar dari (nrow * ncol) ncell = 10M, yang cukup kecil; tetapi saya sering menemukan bahwa saya ingin R membuat dan menahan grafik intensif memori hanya ketika saya meminta dari banyak basis data. Di masa depan laptop 32 GB, beberapa jenis masalah memori ini akan hilang. Namun daya pikat menggunakan database untuk menyimpan data dan kemudian menggunakan memori R untuk hasil kueri yang dihasilkan dan grafik masih mungkin berguna. Beberapa keunggulannya adalah:

(1) Data tetap dimuat di basis data Anda. Anda cukup menyambungkan kembali dalam pgadmin ke database yang Anda inginkan saat menghidupkan kembali laptop Anda.

(2) Memang benar R dapat melakukan banyak operasi statistik dan grafik yang lebih baik daripada SQL. Tapi saya pikir SQL lebih baik dirancang untuk query data dalam jumlah besar daripada 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)
rferrisx
sumber
3

Saya membaca data dengan sangat cepat menggunakan arrowpaket baru . Tampaknya berada pada tahap yang cukup awal.

Secara khusus, saya menggunakan format kolom parket . Ini mengonversi kembali ke data.framedalam R, tetapi Anda bisa mendapatkan speedup lebih dalam jika tidak. Format ini nyaman karena dapat digunakan dari Python juga.

Kasus penggunaan utama saya untuk ini adalah pada server RShiny yang cukup terkendali. Untuk alasan ini, saya lebih suka menyimpan data yang melekat pada Aplikasi (yaitu, keluar dari SQL), dan karena itu memerlukan ukuran file kecil serta kecepatan.

Artikel tertaut ini memberikan tolok ukur dan tinjauan umum yang baik. Saya telah mengutip beberapa poin menarik di bawah ini.

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

Ukuran file

Artinya, file Parket hanya setengah dari CSV yang di-gzip. Salah satu alasan mengapa file Parket sangat kecil adalah karena kamus-encoding (juga disebut "kompresi kamus"). Kompresi kamus dapat menghasilkan kompresi yang jauh lebih baik daripada menggunakan kompresor byte tujuan umum seperti LZ4 atau ZSTD (yang digunakan dalam format FST). Parket dirancang untuk menghasilkan file yang sangat kecil yang cepat dibaca.

Baca Kecepatan

Ketika mengendalikan berdasarkan tipe output (mis. Membandingkan semua data R. Output frame satu sama lain) kita melihat kinerja Parket, Bulu, dan FST berada dalam margin yang relatif kecil satu sama lain. Hal yang sama berlaku untuk output panda. DataFrame. data.table :: fread sangat bersaing dengan ukuran file 1,5 GB tetapi tertinggal yang lain pada CSV 2,5 GB.


Tes Independen

Saya melakukan beberapa pembandingan independen pada set data simulasi 1.000.000 baris. Pada dasarnya saya mengocok banyak hal di sekitar untuk mencoba menantang kompresi. Saya juga menambahkan bidang teks pendek kata-kata acak dan dua faktor simulasi.

Data

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

Baca dan tulis

Menulis data itu mudah.

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)

Membaca data juga mudah.

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)

Saya diuji membaca data ini terhadap beberapa opsi yang bersaing, dan memang mendapatkan hasil yang sedikit berbeda dibandingkan dengan artikel di atas, yang diharapkan.

benchmarking

File ini jauh dari ukuran artikel benchmark, jadi mungkin itulah bedanya.

Tes

  • rds: test_data.rds (20,3 MB)
  • parquet2_native: (14,9 MB dengan kompresi lebih tinggi dan as_data_frame = FALSE)
  • parquet2: test_data2.parquet (14.9 MB dengan kompresi lebih tinggi)
  • parket: test_data.parquet (40,7 MB)
  • fst2: test_data2.fst (27,9 MB dengan kompresi lebih tinggi)
  • pertama: test_data.fst (76,8 MB)
  • fread2: test_data.csv.gz (23.6MB)
  • fread: test_data.csv (98.7MB)
  • feather_arrow: test_data.feather (157,2 MB dibaca bersama arrow)
  • feather: test_data.feather (157,2 MB dibaca bersama feather)

Pengamatan

Untuk file khusus ini, freadsebenarnya sangat cepat. Saya suka ukuran file kecil dari parquet2tes yang sangat terkompresi . Saya dapat menginvestasikan waktu untuk bekerja dengan format data asli daripada data.framejika saya benar-benar perlu mempercepat.

Ini fstjuga pilihan yang bagus. Saya akan menggunakan fstformat yang sangat terkompresi atau sangat terkompresi parquettergantung pada apakah saya memerlukan kecepatan atau ukuran file trade off.

Adam
sumber
0

Alih-alih read.table konvensional saya merasa takut adalah fungsi yang lebih cepat. Menentukan atribut tambahan seperti hanya memilih kolom yang diperlukan, menentukan colclass dan string karena faktor akan mengurangi waktu yang diperlukan untuk mengimpor file.

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"))
Aayush Agrawal
sumber
0

Saya sudah mencoba semuanya di atas dan [readr] [1] membuat pekerjaan terbaik. Saya hanya memiliki RAM 8GB

Loop untuk 20 file, masing-masing 5gb, 7 kolom:

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)))
Brun Ijbh
sumber