Lire un fichier Excel directement à partir d'un script R

95

Comment puis-je lire un fichier Excel directement dans R? Ou devrais-je d'abord exporter les données vers un fichier texte ou CSV et importer ce fichier dans R?

waanders
la source
@Sacha Epskamp: avec xlsReadWrite, vous n'avez même pas besoin d'installer Perl.
Joris Meys
1
gdatala version 2.8.2 lit les xlsxfichiers avec la read.xlsfonction
Ben
1
Voir mon avertissement (comme réponse ci-dessous) concernant la perte de précision possible si vous exportez les données au format texte à partir d'Excel.
russellpierce
1
xlsxpaquet pour xlsx / xlsm / xls, je ne sais pas pour xlam etc.
Qbik
2
"Je ne vois jamais de raison de ne pas exporter d'abord vers un fichier texte". Que diriez-vous de ceci: lorsque j'exporte au format CSV, l'un des champs dont j'ai besoin n'est pas écrit. Cela ressemble à une sorte de DRM, mais comme je n'ai pas écrit la feuille de calcul, je ne sais pas.
Nate Reed

Réponses:

41

Oui. Voir la page sur le wiki R . Réponse courte: à read.xlspartir du gdatapaquet fonctionne la plupart du temps (bien que vous ayez besoin d'avoir Perl installé sur votre système - généralement déjà vrai sur MacOS et Linux, mais fait un pas supplémentaire sur Windows, c'est-à-dire voir http://strawberryperl.com/ ). Il existe diverses mises en garde et alternatives répertoriées sur la page du wiki R.

La seule raison que je vois pour ne pas le faire directement est que vous voudrez peut-être examiner la feuille de calcul pour voir si elle présente des problèmes (en-têtes étranges, plusieurs feuilles de calcul [vous ne pouvez en lire qu’une à la fois, bien que vous puissiez évidemment toutes les parcourir]) , parcelles incluses, etc.). Mais pour une feuille de calcul rectangulaire bien formée avec des nombres simples et des données de caractères (c'est-à-dire des nombres, des dates, des formules avec des erreurs de division par zéro, des valeurs manquantes, etc., etc.), je n'ai généralement aucun problème avec ce processus.

Ben Bolker
la source
6
Il y a beaucoup de problèmes potentiels à considérer que j'ai rencontrés personnellement. Les champs avec des nombres avec des virgules doivent être supprimés et convertis en numérique dans R. Les champs avec "-" doivent être recodés en NA. La recommandation générale est de vraiment regarder vos chiffres dans Excel et de vous assurer qu'ils sont correctement traduits en R.
Brandon Bertelsen
3
Vous ne pouvez pas discuter avec "vous avez vraiment besoin de regarder vos chiffres" ... quel est le problème avec les champs "-"? résout na.strings="-"le problème? Combien de ces problèmes sont génériques et combien d'entre eux (par exemple les champs numériques avec des virgules) peuvent être résolus avec d'autres outils tels que XLConnect ...?
Ben Bolker
1
Ce commentaire s'adressait à l'OP, pas à toi Ben, ma faute pour un mauvais placement.
Brandon Bertelsen
1
Anecdote pertinente: read.xlsréussir à la lecture d' une très grande feuille à partir d' un fichier Excel où les deux XLConnectet a xlsxéchoué (je crois parce qu'ils reposent tous deux sur Apache POI )
Matt Parker
49

Permettez-moi de répéter ce que @Chase a recommandé: utilisez XLConnect .

Les raisons d'utiliser XLConnect sont, à mon avis:

  1. Plateforme croisée. XLConnect est écrit en Java et, par conséquent, fonctionnera sous Win, Linux, Mac sans changement de votre code R (sauf éventuellement les chaînes de chemin)
  2. Rien d'autre à charger. Installez simplement XLConnect et continuez avec la vie.
  3. Vous avez uniquement mentionné la lecture de fichiers Excel, mais XLConnect écrira également des fichiers Excel, y compris la modification du formatage des cellules. Et il le fera à partir de Linux ou Mac, pas seulement de Win.

XLConnect est quelque peu nouveau par rapport à d'autres solutions, il est donc moins fréquemment mentionné dans les articles de blog et les documents de référence. Pour moi, cela a été très utile.

JD Long
la source
48

Et maintenant, il y a readxl :

Le package readxl facilite l'extraction des données d'Excel et dans R. Comparé aux packages existants (par exemple gdata, xlsx, xlsReadWrite, etc.) readxl n'a pas de dépendances externes, il est donc facile à installer et à utiliser sur tous les systèmes d'exploitation. Il est conçu pour fonctionner avec des données tabulaires stockées dans une seule feuille.

readxl est construit au-dessus de la bibliothèque libxls C, qui fait abstraction de la plupart des complexités du format binaire sous-jacent.

Il prend en charge le format .xls hérité et .xlsx

readxl est disponible depuis CRAN, ou vous pouvez l'installer depuis github avec:

# install.packages("devtools")
devtools::install_github("hadley/readxl")

Usage

library(readxl)

# read_excel reads both xls and xlsx files
read_excel("my-old-spreadsheet.xls")
read_excel("my-new-spreadsheet.xlsx")

# Specify sheet with a number or name
read_excel("my-spreadsheet.xls", sheet = "data")
read_excel("my-spreadsheet.xls", sheet = 2)

# If NAs are represented by something other than blank cells,
# set the na argument
read_excel("my-spreadsheet.xls", na = "NA")

Notez que bien que la description indique `` pas de dépendances externes '', elle nécessite le Rcpppackage , qui à son tour nécessite Rtools (pour Windows) ou Xcode (pour OSX), qui sont des dépendances externes à R. Bien que de nombreuses personnes les aient installés pour d'autres raisons .

Ben
la source
3
Beaucoup plus rapide que xlsx. Le temps de lecture est comme read.xlsx2, mais il en déduit les types.
Steve Rowe
1
@SteveRowe voir une nouvelle réponse pour certains benchmarks objectifs (tentés) confirmant cela
MichaelChirico
Existe-t-il un moyen de lire les chaînes en tant que facteurs en utilisant read_excel? J'aime la vitesse par rapport à read.xlsx, mais devoir ensuite convertir manuellement les colonnes de caractères en facteurs va à l'encontre de l'objectif.
coip
2
+1 pour le fait qu'il n'a pas de dépendances. Je déteste avoir à installer java. Et je l'ai essayé et cela fonctionne très bien pour moi.
Bastian
2
readxl et openxlsx sont les meilleurs. readxl est plus rapide mais ne permet pas d'écrire. Quoi qu'il en soit, aucun d'entre eux ne fonctionne bien lorsque vous essayez de spécifier des classes / types de colonnes.
skan
29

EDIT 2015-Octobre: Comme d'autres l'ont commenté ici, les packages openxlsxet readxlsont de loin plus rapides que le xlsxpackage et parviennent en fait à ouvrir des fichiers Excel plus volumineux (> 1500 lignes et> 120 colonnes). @MichaelChirico démontre que readxlc'est mieux lorsque la vitesse est préférée et openxlsxremplace la fonctionnalité fournie par le xlsxpackage. Si vous recherchez un package pour lire, écrire et modifier des fichiers Excel en 2015, choisissez le openxlsxau lieu de xlsx.

Pré-2015: j'ai utilisé le xlsxpackage . Cela a changé mon flux de travail avec Excel et R. Plus de pop-ups ennuyeux me demandant si je suis sûr de vouloir enregistrer ma feuille Excel au format .txt. Le package écrit également des fichiers Excel.

Cependant, je trouve que la read.xlsxfonction est lente lors de l'ouverture de gros fichiers Excel. read.xlsx2est considérablement plus rapide, mais ne quitte pas la classe vectorielle des colonnes data.frame. Vous devez utiliser la colClassescommande pour spécifier les classes de colonnes souhaitées, si vous utilisez la read.xlsx2fonction. Voici un exemple pratique:

read.xlsx("filename.xlsx", 1)lit votre fichier et rend les classes de colonnes data.frame presque utiles, mais est très lent pour les grands ensembles de données. Fonctionne également pour les .xlsfichiers.

read.xlsx2("filename.xlsx", 1)est plus rapide, mais vous devrez définir manuellement les classes de colonnes. Un raccourci consiste à exécuter la commande deux fois (voir l'exemple ci-dessous). characterLa spécification convertit vos colonnes en facteurs. Utilisation Dateet POSIXctoptions pour le temps.

coln <- function(x){y <- rbind(seq(1,ncol(x))); colnames(y) <- colnames(x)
rownames(y) <- "col.number"; return(y)} # A function to see column numbers

data <- read.xlsx2("filename.xlsx", 1) # Open the file 

coln(data)    # Check the column numbers you want to have as factors

x <- 3 # Say you want columns 1-3 as factors, the rest numeric

data <- read.xlsx2("filename.xlsx", 1, colClasses= c(rep("character", x),
rep("numeric", ncol(data)-x+1)))
Mikko
la source
25

Compte tenu de la prolifération de différentes façons de lire un fichier Excel Ret 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 xlsxdepuis 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, readxlet 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 RODBCparce que je suis sous Linux; XLConnectcar 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 xlsReadWriteparce 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=1000Let NN=25000L(réinitialisation de la graine avant chaque déclaration de ce qui data.frameprécède) pour tenir compte des différences en ce qui concerne la taille du fichier Excel. gcest 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 readxlva de même pour le gagnant, avec un perdant openxlsxcompétitif et gdataclair. 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, xlsxest 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 readxlva de même pour le vainqueur en matière de vitesse. gdatamieux 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 openxlsxsont 1) ses nombreuses autres méthodes ( readxlest conçu pour ne faire qu'une seule chose, ce qui explique probablement en partie pourquoi il est si rapide), en particulier sa write.xlsxfonction, et 2) (plus un inconvénient pour readxl) l' col_typesargument en readxlseulement (comme de cet écrit) accepte certains non standard R: "text"au lieu de "character"et "date"au lieu de "Date".

MichaelChirico
la source
Ce serait formidable si vous ajoutiez également la référence pour XLConnect. Commentez également que readxl n'est pas capable d'écrire. xlsx et openxlsx ne fonctionnent pas correctement avec l'option col_types ou colClasses.
skan
@skan J'ai d'abord fait des tests avec XLConnectmais c'est très lent; Je crois que readxlles inconvénients de mon article ont été suffisamment traités dans mon dernier paragraphe; et je n'ai pas d'expérience similaire à la vôtre avec xlsxou openxlsxcar j'utilise régulièrement les deux pour spécifier les types.
MichaelChirico
13
library(RODBC)
file.name <- "file.xls"
sheet.name <- "Sheet Name"

## Connect to Excel File Pull and Format Data
excel.connect <- odbcConnectExcel(file.name)
dat <- sqlFetch(excel.connect, sheet.name, na.strings=c("","-"))
odbcClose(excel.connect)

Personnellement, j'aime RODBC et je peux le recommander.

Brandon Bertelsen
la source
7
Attention: ODBC peut parfois être difficile à exécuter sur des plates-formes autres que Windows.
JD Long
1
@JD Long et même sous Windows, c'est un PITA. Pas de moment sexy pour moi et ODBC sur W7 64 bits ...
Roman Luštrik
4
Chargement du package requis: Erreur RODBC dans odbcConnectExcel (file.name): odbcConnectExcel est uniquement utilisable avec Windows 32 bits
andrekos
6

Une autre solution est le xlsReadWritepackage, qui ne nécessite pas d'installations supplémentaires mais vous oblige à télécharger le shlib supplémentaire avant de l'utiliser pour la première fois en:

require(xlsReadWrite)
xls.getshlib()

Oublier cela peut provoquer une frustration totale. J'y suis allé et tout ça ...

Remarque: vous voudrez peut-être envisager de convertir en un format basé sur du texte (par exemple, csv) et de lire à partir de là. Ceci pour plusieurs raisons:

  • quelle que soit votre solution (RODBC, gdata, xlsReadWrite), des choses étranges peuvent se produire lorsque vos données sont converties. Surtout les dates peuvent être assez lourdes. Le HFWutilspackage a quelques outils pour gérer les dates EXCEL (par commentaire de @Ben Bolker).

  • si vous avez de grandes feuilles, la lecture de fichiers texte est plus rapide que la lecture depuis EXCEL.

  • pour les fichiers .xls et .xlsx, différentes solutions peuvent être nécessaires. Par exemple, le package xlsReadWrite ne prend actuellement pas en charge .xlsx AFAIK. gdatavous oblige à installer des bibliothèques Perl supplémentaires pour le support .xlsx. xlsxpackage peut gérer les extensions du même nom.

Joris Meys
la source
@Ben Thx pour le conseil, je vais l'inclure dans ma réponse. Je n'ai pas essayé d'être complet cependant, car la page wiki vers laquelle les réponses acceptées sont liées est déjà assez complète. Mais il ne mentionne pas le package HFWutils.
Joris Meys
1
-1; Voyez ma réponse. TL: DR: Excel n'enregistre pas un jeu de données de précision complète dans csv (ou dans le presse-papiers). Seules les valeurs visibles sont conservées.
russellpierce
5

Comme indiqué ci-dessus dans de nombreuses autres réponses, il existe de nombreux bons packages qui se connectent au fichier XLS / X et obtiennent les données de manière raisonnable. Cependant, vous devez être averti qu'en aucun cas vous ne devez utiliser le presse-papiers (ou un fichier .csv) pour récupérer des données d'Excel. Pour voir pourquoi, entrez =1/3dans une cellule dans Excel. Maintenant, réduisez le nombre de points décimaux visibles par vous à deux. Puis copiez et collez les données dans R. Enregistrez maintenant le CSV. Vous remarquerez que dans les deux cas, Excel n'a utilement conservé que les données qui vous étaient visibles via l'interface et que vous avez perdu toute la précision de vos données source réelles.

russellpierce
la source
1
J'aimerais savoir qui pensait que la fidélité numérique n'était pas pertinente / importante.
russellpierce
1
Bon avertissement. Cependant, cela dépend du package que vous utilisez. certains ne tombent pas dans ce piège.
RockScience
@RocketScience Il s'agit d'un choix de conception fondamental dans l'export CSV par Excel. Avez-vous un exemple de package qui utilise le presse-papiers qui ne présente pas ce problème? Les paquets analysant directement le fichier xls xlsx auraient tendance à ne pas tomber dans ce piège. Ainsi, la portée spécifique de mon avertissement.
russellpierce
sous Unix, vous pouvez essayer gnumeric::read.gnumeric.sheet. Sur Windows, je ne suis pas sûr à 100%, mais je pense que cela gdata::read.xlsdevrait aussi bien fonctionner (il faut cependant installer perl)
RockScience
@RockScience Respectueusement, gdata :: read.xls ne fonctionne pas sur les données du presse-papiers (à moins que vous ne fassiez tout votre possible) et gnumeric n'est pas Excel. Donc, en l'absence de preuve extraordinaire, mon avertissement tient. Il y a tellement d'autres bonnes options en réponse à cette question - espérons que les gens les utiliseront à la place.
russellpierce
5

En développant la réponse fournie par @Mikko, vous pouvez utiliser une astuce intéressante pour accélérer les choses sans avoir à «connaître» vos classes de colonnes à l'avance. Utilisez simplement read.xlsxpour saisir un nombre limité d'enregistrements pour déterminer les classes, puis faites un suivi avecread.xlsx2

Exemple

# just the first 50 rows should do...
df.temp <- read.xlsx("filename.xlsx", 1, startRow=1, endRow=50) 
df.real <- read.xlsx2("filename.xlsx", 1, 
                      colClasses=as.vector(sapply(df.temp, mode)))
JasonAizkalns
la source
1
Votre solution retourne numericpour factorsmon ordinateur. read.xlsxutilise characteren readColumnsfonction pour spécifier des facteurs. Je suis sûr qu'il ya une façon plus élégante d'obtenir des facteurs comme des personnages, mais voici une version modifiée de votre fonction: travaux df.real <- read.xlsx2("filename.xlsx", 1, colClasses=gsub("factor", "character", as.vector(sapply(df.temp, class)))).
Mikko
Cela ne fonctionne que dans la mesure où le type de colonne peut être correctement déterminé par la première ligne. En général, on analyse plus que la première ligne pour faire cette détermination. La réponse pourrait être améliorée pour répondre au commentaire de aaa90210 en nommant le paquet d'où proviennent ces fonctions.
russellpierce
1

Un fichier Excel peut être lu directement dans R comme suit:

my_data <- read.table(file = "xxxxxx.xls", sep = "\t", header=TRUE)

Lecture de fichiers xls et xlxs à l'aide du package readxl

library("readxl")
my_data <- read_excel("xxxxx.xls")
my_data <- read_excel("xxxxx.xlsx")
Ashok Kumar Jayaraman
la source