Dada a proliferação de diferentes maneiras de ler um arquivo do Excel Re 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 xlsxdesde 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 RODBCporque estou no Linux; XLConnectporque 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 xlsReadWriteporque não é mais compatível com a minha versão do R(parece ter sido desativado).
Em seguida, executei benchmarks com NN=1000Le NN=25000L(redefinindo a semente antes de cada declaração data.frameacima) 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 openxlsxcompetitivo e gdataclaro. 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 openxlsxsã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.xlsxfunção, e 2) (mais uma desvantagem para readxl) o col_typesargumento em readxlapenas (como desta redação) aceita alguns não padrão R: em "text"vez de "character"e em "date"vez de "Date".