Dada a proliferação de diferentes maneiras de ler um arquivo do Excel R
e a abundância de respostas aqui, pensei em tentar esclarecer qual das opções mencionadas aqui tem melhor desempenho (em algumas situações simples).
Eu mesmo tenho usado xlsx
desde que comecei a usar R
, por inércia, se nada mais, e recentemente percebi que não parece haver nenhuma informação objetiva sobre qual pacote funciona melhor.
Qualquer exercício de benchmarking está repleto de dificuldades, pois alguns pacotes certamente lidam com certas situações melhor do que outros, e uma cascata de outras advertências.
Dito isso, estou usando um conjunto de dados (reproduzível) que acho que está em um formato bastante comum (8 campos de string, 3 numéricos, 1 inteiro, 3 datas):
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)
)
Eu, então, escreveu isto para CSV e inaugurado em LibreOffice e salva-lo como um arquivo .xlsx, então aferido 4 dos pacotes mencionados neste tópico: xlsx
, openxlsx
, readxl
, e gdata
, usando as opções padrão (Eu também tentei uma versão de haver ou não eu especificar os tipos de coluna, mas isso não alterou as classificações).
Estou excluindo RODBC
porque estou no Linux; XLConnect
porque parece que seu objetivo principal não é ler em planilhas únicas do Excel, mas importar pastas de trabalho inteiras do Excel, portanto, colocar seu cavalo na corrida apenas em suas capacidades de leitura parece injusto; e xlsReadWrite
porque não é mais compatível com a minha versão do R
(parece ter sido desativado).
Em seguida, executei benchmarks com NN=1000L
e NN=25000L
(redefinindo a semente antes de cada declaração data.frame
acima) para permitir as diferenças em relação ao tamanho do arquivo do Excel. gc
é principalmente para xlsx
, que às vezes pode criar obstruções de memória. Sem mais delongas, aqui estão os resultados que encontrei:
Arquivo Excel de 1.000 linhas
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
Assim readxl
é o vencedor, com um perdedor openxlsx
competitivo e gdata
claro. Tomando cada medida em relação ao mínimo da coluna:
# 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
Vemos o meu favorito, xlsx
é 60% mais lento do que readxl
.
Arquivo Excel de 25.000 linhas
Devido ao tempo que leva, fiz apenas 20 repetições no arquivo maior, caso contrário, os comandos eram idênticos. Aqui estão os dados brutos:
# 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
Aqui estão os dados relativos:
# 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
Então, readxl
é o vencedor claro quando se trata de velocidade. gdata
é melhor ter algo mais a seu favor, já que é dolorosamente lento para ler arquivos do Excel, e esse problema só é agravado para tabelas maiores.
Dois empates openxlsx
são 1) seus outros métodos extensivos ( readxl
é projetado para fazer apenas uma coisa, o que provavelmente é parte do motivo pelo qual é tão rápido), especialmente sua write.xlsx
função, e 2) (mais uma desvantagem para readxl
) o col_types
argumento em readxl
apenas (como desta redação) aceita alguns não padrão R
: em "text"
vez de "character"
e em "date"
vez de "Date"
.