Data la proliferazione di diversi modi per leggere un file Excel R
e la pletora di risposte qui, ho pensato di provare a far luce su quale delle opzioni menzionate qui si comporta meglio (in poche semplici situazioni).
Io stesso lo uso da xlsx
quando ho iniziato a usare R
, per inerzia se non altro, e recentemente ho notato che non sembra esserci alcuna informazione oggettiva su quale pacchetto funzioni meglio.
Qualsiasi esercizio di benchmarking è irto di difficoltà poiché alcuni pacchetti sono sicuri di gestire determinate situazioni meglio di altri e una cascata di altri avvertimenti.
Detto questo, sto usando un set di dati (riproducibile) che penso sia in un formato abbastanza comune (8 campi stringa, 3 numerici, 1 intero, 3 date):
set.seed(51423)
data.frame(
str1 = sample(sprintf("%010d", 1:NN)), #ID field 1
str2 = sample(sprintf("%09d", 1:NN)), #ID field 2
#varying length string field--think names/addresses, etc.
str3 =
replicate(NN, paste0(sample(LETTERS, sample(10:30, 1L), TRUE),
collapse = "")),
#factor-like string field with 50 "levels"
str4 = sprintf("%05d", sample(sample(1e5, 50L), NN, TRUE)),
#factor-like string field with 17 levels, varying length
str5 =
sample(replicate(17L, paste0(sample(LETTERS, sample(15:25, 1L), TRUE),
collapse = "")), NN, TRUE),
#lognormally distributed numeric
num1 = round(exp(rnorm(NN, mean = 6.5, sd = 1.5)), 2L),
#3 binary strings
str6 = sample(c("Y","N"), NN, TRUE),
str7 = sample(c("M","F"), NN, TRUE),
str8 = sample(c("B","W"), NN, TRUE),
#right-skewed integer
int1 = ceiling(rexp(NN)),
#dates by month
dat1 =
sample(seq(from = as.Date("2005-12-31"),
to = as.Date("2015-12-31"), by = "month"),
NN, TRUE),
dat2 =
sample(seq(from = as.Date("2005-12-31"),
to = as.Date("2015-12-31"), by = "month"),
NN, TRUE),
num2 = round(exp(rnorm(NN, mean = 6, sd = 1.5)), 2L),
#date by day
dat3 =
sample(seq(from = as.Date("2015-06-01"),
to = as.Date("2015-07-15"), by = "day"),
NN, TRUE),
#lognormal numeric that can be positive or negative
num3 =
(-1) ^ sample(2, NN, TRUE) * round(exp(rnorm(NN, mean = 6, sd = 1.5)), 2L)
)
Ho quindi scritto questo per csv e inaugurato nel LibreOffice e salvato come file .xlsx, poi messo a confronto 4 dei pacchetti citati in questa discussione: xlsx
,openxlsx
, readxl
, e gdata
, utilizzando le opzioni predefinite (ho anche provato una versione di se o non ho specificare i tipi di colonna, ma ciò non ha modificato le classifiche).
Escludo RODBC
perché sono su Linux; XLConnect
perché sembra che il suo scopo principale non sia leggere in singoli fogli Excel ma importare intere cartelle di lavoro Excel, quindi mettere il suo cavallo in gara solo sulle sue capacità di lettura sembra ingiusto; exlsReadWrite
perché non è più compatibile con la mia versione di R
(sembra essere stata gradualmente eliminata).
Ho quindi eseguito i benchmark con NN=1000L
e NN=25000L
(reimpostando il seme prima di ogni dichiarazione di quanto data.frame
sopra) per tenere conto delle differenze rispetto alla dimensione del file Excel.gc
è principalmente per xlsx
, che ho trovato a volte può creare intasamenti di memoria. Senza ulteriori indugi, ecco i risultati che ho trovato:
File Excel di 1.000 righe
benchmark1k <-
microbenchmark(times = 100L,
xlsx = {xlsx::read.xlsx2(fl, sheetIndex=1); invisible(gc())},
openxlsx = {openxlsx::read.xlsx(fl); invisible(gc())},
readxl = {readxl::read_excel(fl); invisible(gc())},
gdata = {gdata::read.xls(fl); invisible(gc())})
# Unit: milliseconds
# expr min lq mean median uq max neval
# xlsx 194.1958 199.2662 214.1512 201.9063 212.7563 354.0327 100
# openxlsx 142.2074 142.9028 151.9127 143.7239 148.0940 255.0124 100
# readxl 122.0238 122.8448 132.4021 123.6964 130.2881 214.5138 100
# gdata 2004.4745 2042.0732 2087.8724 2062.5259 2116.7795 2425.6345 100
Quindi readxl
è il vincitore, con openxlsx
competitivo e gdata
un chiaro perdente. Prendendo ogni misura relativa al minimo della colonna:
# expr min lq mean median uq max
# 1 xlsx 1.59 1.62 1.62 1.63 1.63 1.65
# 2 openxlsx 1.17 1.16 1.15 1.16 1.14 1.19
# 3 readxl 1.00 1.00 1.00 1.00 1.00 1.00
# 4 gdata 16.43 16.62 15.77 16.67 16.25 11.31
Vediamo il mio preferito, xlsx
è del 60% più lento di readxl
.
File Excel di 25.000 righe
A causa del tempo necessario, ho fatto solo 20 ripetizioni sul file più grande, altrimenti i comandi erano identici. Ecco i dati grezzi:
# Unit: milliseconds
# expr min lq mean median uq max neval
# xlsx 4451.9553 4539.4599 4738.6366 4762.1768 4941.2331 5091.0057 20
# openxlsx 962.1579 981.0613 988.5006 986.1091 992.6017 1040.4158 20
# readxl 341.0006 344.8904 347.0779 346.4518 348.9273 360.1808 20
# gdata 43860.4013 44375.6340 44848.7797 44991.2208 45251.4441 45652.0826 20
Ecco i dati relativi:
# expr min lq mean median uq max
# 1 xlsx 13.06 13.16 13.65 13.75 14.16 14.13
# 2 openxlsx 2.82 2.84 2.85 2.85 2.84 2.89
# 3 readxl 1.00 1.00 1.00 1.00 1.00 1.00
# 4 gdata 128.62 128.67 129.22 129.86 129.69 126.75
Così readxl
è il chiaro vincitore quando si tratta di velocità. gdata
meglio avere qualcos'altro da fare, poiché è dolorosamente lento nella lettura dei file Excel e questo problema è aggravato solo per le tabelle più grandi.
Due svantaggi openxlsx
sono 1) i suoi estesi altri metodi ( readxl
è progettato per fare solo una cosa, che probabilmente è parte del motivo per cui è così veloce), in particolare la sua write.xlsx
funzione, e 2) (più di uno svantaggio per readxl
) l' col_types
argomento readxl
solo (come di questo scritto) accetta alcuni non standard R
: "text"
invece di "character"
e "date"
invece di "Date"
.