Compte tenu de la prolifération de différentes façons de lire un fichier Excel R
et de la pléthore de réponses ici, j'ai pensé essayer de faire la lumière sur les options mentionnées ici qui fonctionnent le mieux (dans quelques situations simples).
J'utilise moi-même xlsx
depuis que j'ai commencé à utiliser R
, pour l'inertie si rien d'autre, et j'ai récemment remarqué qu'il ne semble pas y avoir d'informations objectives sur le package qui fonctionne le mieux.
Tout exercice d'analyse comparative est semé d'embûches car certains packages sont sûrs de gérer certaines situations mieux que d'autres, et une cascade d'autres mises en garde.
Cela dit, j'utilise un ensemble de données (reproductible) qui, à mon avis, est dans un format assez courant (8 champs de chaîne, 3 numériques, 1 entier, 3 dates):
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)
)
J'ai alors écrit cela csv et ouvert dans LibreOffice et enregistré comme un fichier .xlsx, alors étalonnées 4 des paquets mentionnés dans ce fil: xlsx
, openxlsx
, readxl
et gdata
, en utilisant les options par défaut (j'ai essayé une version de savoir si oui ou non je spécifier les types de colonnes, mais cela n'a pas changé le classement).
J'exclus RODBC
parce que je suis sous Linux; XLConnect
car il semble que son objectif principal ne soit pas de lire dans des feuilles Excel simples mais d'importer des classeurs Excel entiers, donc mettre son cheval dans la course uniquement sur ses capacités de lecture semble injuste; et xlsReadWrite
parce qu'il n'est plus compatible avec ma version de R
(semble avoir été supprimée).
J'ai ensuite exécuté des tests de performance avec NN=1000L
et NN=25000L
(réinitialisation de la graine avant chaque déclaration de ce qui data.frame
précède) pour tenir compte des différences en ce qui concerne la taille du fichier Excel. gc
est principalement pour xlsx
, que j'ai trouvé parfois peut créer des bouchons de mémoire. Sans plus tarder, voici les résultats que j'ai trouvés:
Fichier Excel de 1000 lignes
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
Il en readxl
va de même pour le gagnant, avec un perdant openxlsx
compétitif et gdata
clair. En prenant chaque mesure par rapport au minimum de la colonne:
# 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
Nous voyons mon propre favori, xlsx
est 60% plus lent que readxl
.
Fichier Excel de 25 000 lignes
En raison du temps que cela prend, je n'ai fait que 20 répétitions sur le plus gros fichier, sinon les commandes étaient identiques. Voici les données brutes:
# 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
Voici les données relatives:
# 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
Il en readxl
va de même pour le vainqueur en matière de vitesse. gdata
mieux vaut avoir autre chose à faire, car la lecture des fichiers Excel est extrêmement lente et ce problème ne fait qu'exacerber les tables plus volumineuses.
Deux inconvénients de openxlsx
sont 1) ses nombreuses autres méthodes ( readxl
est conçu pour ne faire qu'une seule chose, ce qui explique probablement en partie pourquoi il est si rapide), en particulier sa write.xlsx
fonction, et 2) (plus un inconvénient pour readxl
) l' col_types
argument en readxl
seulement (comme de cet écrit) accepte certains non standard R
: "text"
au lieu de "character"
et "date"
au lieu de "Date"
.