Leggi un file Excel direttamente da uno script R.


95

Come posso leggere un file Excel direttamente in R? O dovrei prima esportare i dati in un file di testo o CSV e importare quel file in R?


@Sacha Epskamp: con xlsReadWrite, non è nemmeno necessario installare Perl.
Joris Meys

1
gdatala versione 2.8.2 legge i xlsxfile con la read.xlsfunzione
Ben

1
Vedi il mio avviso (come risposta di seguito) in merito alla possibile perdita di precisione se esporti i dati in un formato di testo da Excel.
russellpierce

1
xlsxpacchetto per xlsx / xlsm / xls, non so xlam ecc.
Qbik

2
"Non vedo mai un motivo per non esportare prima in un file di testo". Che ne dici di questo: quando esporto in CSV, uno dei campi di cui ho bisogno non viene scritto. Sembra una sorta di DRM ma dal momento che non ho scritto il foglio di calcolo non lo so.
Nate Reed

Risposte:


41

Sì. Vedere pagina dedicata sul wiki R . Risposta breve: read.xlsdal gdatapacchetto funziona la maggior parte del tempo (anche se è necessario che Perl sia installato sul sistema - di solito è già vero su MacOS e Linux, ma richiede un passaggio in più su Windows, ad esempio vedere http://strawberryperl.com/ ). Ci sono vari avvertimenti e alternative, elencati nella pagina wiki R.

L'unico motivo per cui vedo di non farlo direttamente è che potresti voler esaminare il foglio di calcolo per vedere se ha difetti (intestazioni strane, fogli di lavoro multipli [puoi leggerne solo uno alla volta, anche se puoi ovviamente scorrere tutti in loop) , incluse trame, ecc.). Ma per un foglio di calcolo rettangolare ben formato con numeri semplici e dati di caratteri (cioè, numeri non formattati con virgole, date, formule con errori di divisione per zero, valori mancanti, ecc. Ecc.) In genere non ho problemi con questo processo.


6
Ci sono molti potenziali problemi da considerare che ho incontrato personalmente. I campi con numeri con virgola devono essere rimossi e convertiti in numerici in R. I campi con "-" devono essere ricodificati in NA. La raccomandazione generale è di guardare davvero i tuoi numeri in Excel e assicurarti che vengano tradotti correttamente in R.
Brandon Bertelsen

3
Non puoi discutere con "hai davvero bisogno di guardare i tuoi numeri" ... qual è il problema con i campi "-"? non na.strings="-"affrontare il problema? Quanti di questi problemi sono generici e quanti di essi (es. Campi numerici con virgole) possono essere risolti con altri strumenti come XLConnect ...?
Ben Bolker

1
Quel commento era diretto all'OP, non a te Ben, colpa mia per il cattivo posizionamento.
Brandon Bertelsen

1
Aneddoto rilevante: read.xlsriuscire a leggere un foglio molto grande da un file Excel in cui entrambi XLConnecte xlsxfallito (credo perché entrambi si basano su Apache POI )
Matt Parker

49

Permettetemi di ribadire ciò che @Chase ha consigliato: utilizzare XLConnect .

I motivi per utilizzare XLConnect sono, a mio parere:

  1. Piattaforma multipla. XLConnect è scritto in Java e, quindi, verrà eseguito su Win, Linux, Mac senza modifiche al codice R (tranne possibilmente stringhe di percorso)
  2. Nient'altro da caricare. Installa XLConnect e vai avanti con la vita.
  3. Hai solo menzionato la lettura di file Excel, ma XLConnect scriverà anche file Excel, inclusa la modifica della formattazione delle celle. E lo farà da Linux o Mac, non solo da Win.

XLConnect è un po 'nuovo rispetto ad altre soluzioni, quindi è menzionato meno frequentemente nei post del blog e nei documenti di riferimento. Per me è stato molto utile.


48

E ora c'è readxl :

Il pacchetto readxl semplifica l'estrazione dei dati da Excel e in R. Rispetto ai pacchetti esistenti (ad esempio gdata, xlsx, xlsReadWrite ecc.) Readxl non ha dipendenze esterne quindi è facile da installare e utilizzare su tutti i sistemi operativi. È progettato per funzionare con dati tabulari archiviati in un unico foglio.

readxl è costruito sulla libreria C libxls, che astrae molte delle complessità del formato binario sottostante.

Supporta sia il formato legacy .xls che .xlsx

readxl è disponibile da CRAN, oppure puoi installarlo da GitHub con:

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

Utilizzo

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")

Si noti che mentre la descrizione dice 'nessuna dipendenza esterna', richiede il Rcpppacchetto , che a sua volta richiede Rtools (per Windows) o Xcode (per OSX), che sono dipendenze esterne a R. Sebbene molte persone li abbiano installati per altri motivi .


3
Molto più veloce di xlsx. Il tempo di lettura è come read.xlsx2, ma deduce i tipi.
Steve Rowe

1
@SteveRowe vede una nuova risposta per alcuni (tentati) benchmark oggettivi che lo confermano
MichaelChirico

C'è un modo per leggere le stringhe come fattori che utilizzano read_excel? Mi piace la velocità rispetto a read.xlsx, ma dover quindi convertire manualmente le colonne da caratteri a fattori vanifica lo scopo.
coip

2
+1 per il fatto che non ha dipendenze. Odio dover installare java. E l'ho provato e funziona molto bene per me.
Bastian

2
readxl e openxlsx sono i migliori. readxl è più veloce ma non permette di scrivere. Ad ogni modo, nessuno di loro funziona bene quando si cerca di specificare classi / tipi di colonne.
skan

29

EDIT 2015-ottobre: come altri hanno commentato qui, i pacchetti openxlsxe readxlsono di gran lunga più veloci del xlsxpacchetto e riescono effettivamente ad aprire file Excel più grandi (> 1500 righe e> 120 colonne). @MichaelChirico dimostra che readxlè meglio quando si preferisce la velocità e openxlsxsostituisce la funzionalità fornita dal xlsxpacchetto. Se stai cercando un pacchetto per leggere, scrivere e modificare file Excel nel 2015, scegli openxlsxinvece di xlsx.

Pre-2015: ho usato il xlsxpacchetto . Ha cambiato il mio flusso di lavoro con Excel e R. Niente più fastidiosi pop-up che chiedono, se sono sicuro di voler salvare il mio foglio Excel in formato .txt. Il pacchetto scrive anche file Excel.

Tuttavia, trovo la read.xlsxfunzione lenta, quando apro file Excel di grandi dimensioni. read.xlsx2è notevolmente più veloce, ma non chiude la classe vettoriale delle colonne data.frame. È necessario utilizzare il colClassescomando per specificare le classi di colonna desiderate, se si utilizza read.xlsx2function. Ecco un esempio pratico:

read.xlsx("filename.xlsx", 1)legge il file e rende le classi di colonne data.frame quasi utili, ma è molto lento per set di dati di grandi dimensioni. Funziona anche per i .xlsfile.

read.xlsx2("filename.xlsx", 1)è più veloce, ma dovrai definire manualmente le classi di colonna. Una scorciatoia consiste nell'eseguire il comando due volte (vedere l'esempio sotto). characterla specifica converte le colonne in fattori. Uso Datee POSIXctopzioni per il tempo.

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)))

25

Data la proliferazione di diversi modi per leggere un file Excel Re 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 xlsxquando 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 RODBCperché sono su Linux; XLConnectperché 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=1000Le NN=25000L(reimpostando il seme prima di ogni dichiarazione di quanto data.framesopra) 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 openxlsxcompetitivo e gdataun 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à. gdatameglio 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 openxlsxsono 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.xlsxfunzione, e 2) (più di uno svantaggio per readxl) l' col_typesargomento readxlsolo (come di questo scritto) accetta alcuni non standard R: "text"invece di "character"e "date"invece di "Date".


Sarebbe fantastico se aggiungessi anche il benchmark per XLConnect. Commenta anche che readxl non è in grado di scrivere. xlsx e openxlsx non funzionano correttamente con l'opzione col_types o colClasses.
skan

@skan inizialmente ho eseguito alcuni test XLConnectma è molto lento; Credo che readxlgli svantaggi di sono stati sufficientemente trattati nel mio ultimo paragrafo; e non ho esperienza simile alla tua con xlsxo openxlsxpoiché utilizzo regolarmente entrambi per specificare i tipi.
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)

Personalmente, mi piace RODBC e posso consigliarlo.


7
Avvertenza: ODBC a volte può essere complicato da eseguire su piattaforme diverse da Windows.
JD Long,

1
@JD Long e anche su Windows è una PITA. Nessun momento sexy per me e ODBC su 64 bit W7 ...
Roman Luštrik

4
Caricamento del pacchetto richiesto: errore RODBC in odbcConnectExcel (nome file): odbcConnectExcel è utilizzabile solo con Windows a 32 bit
andrekos


6

Un'altra soluzione è il xlsReadWritepacchetto, che non richiede installazioni aggiuntive ma richiede di scaricare lo shlib aggiuntivo prima di utilizzarlo la prima volta:

require(xlsReadWrite)
xls.getshlib()

Dimenticarlo può causare una frustrazione totale. Ci sono stato e tutto il resto ...

Nota a margine: potresti prendere in considerazione la conversione in un formato basato su testo (es. Csv) e leggere da lì. Questo per una serie di motivi:

  • qualunque sia la tua soluzione (RODBC, gdata, xlsReadWrite), possono accadere cose strane quando i tuoi dati vengono convertiti. Soprattutto le date possono essere piuttosto ingombranti. Il HFWutilspacchetto ha alcuni strumenti per gestire le date EXCEL (secondo il commento di @Ben Bolker).

  • se hai fogli di grandi dimensioni, leggere i file di testo è più veloce che leggere da EXCEL.

  • per i file .xls e .xlsx, potrebbero essere necessarie soluzioni diverse. Ad esempio, il pacchetto xlsReadWrite attualmente non supporta .xlsx AFAIK. gdatarichiede l'installazione di librerie Perl aggiuntive per il supporto .xlsx. xlsxpacchetto può gestire estensioni con lo stesso nome.


@ Ben Thx per il suggerimento, lo includerò nella mia risposta. Tuttavia, non ho cercato di essere completo, poiché la pagina wiki a cui si collega la risposta accettata è già piuttosto completa. Ma non menziona il pacchetto HFWutils.
Joris Meys

1
-1; Vedi la mia risposta. TL: DR: Excel non salva un set di dati di precisione completa in csv (o negli appunti). Vengono mantenuti solo i valori visibili.
russellpierce

5

Come notato sopra in molte delle altre risposte, ci sono molti buoni pacchetti che si collegano al file XLS / X e ottengono i dati in modo ragionevole. Tuttavia, tieni presente che in nessun caso dovresti utilizzare il file degli appunti (o un file .csv) per recuperare i dati da Excel. Per capire perché, entra =1/3in una cella in Excel. Ora, riduci a due il numero di punti decimali visibili. Quindi copia e incolla i dati in R. Ora salva il CSV. Noterai in entrambi i casi che Excel ha mantenuto utilmente solo i dati che ti erano visibili attraverso l'interfaccia e hai perso tutta la precisione nei dati di origine effettivi.


1
Mi piacerebbe sapere chi pensava che la fedeltà numerica non fosse rilevante / importante.
russellpierce

1
Buon avvertimento. Tuttavia dipende dal pacchetto che utilizzi. alcuni non cadono in questa trappola.
RockScience

@RocketScience Questa è una scelta progettuale fondamentale nell'esportazione CSV da Excel. Hai un esempio di un pacchetto che utilizza gli appunti che non presenta questo problema? I pacchetti che analizzano direttamente il file xls xlsx sarebbero inclini a non cadere in questa trappola. Quindi, l'ambito specifico del mio avvertimento.
russellpierce

su Unix puoi provare gnumeric::read.gnumeric.sheet. Su Windows non sono sicuro al 100% ma penso che gdata::read.xlsdovrebbe funzionare anche bene (è necessario installare perl però)
RockScience

@RockScience Rispettosamente, gdata :: read.xls non opera sui dati degli appunti (a meno che tu non esca di mezzo) e gnumeric non è Excel. Quindi, in assenza di prove straordinarie, il mio avvertimento resta. Ci sono così tante altre buone opzioni in risposta a questa domanda: speriamo che le persone usino quelle invece.
russellpierce

5

Espandendo la risposta fornita da @Mikko puoi usare un trucco per velocizzare le cose senza dover "conoscere" in anticipo le classi delle colonne. Usalo semplicemente read.xlsxper prendere un numero limitato di record per determinare le classi e poi seguirloread.xlsx2

Esempio

# 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)))

1
La soluzione torna numericper factorsil mio computer. read.xlsxutilizza characterin readColumnsfunzione per specificare i fattori. Sono sicuro che ci sia un modo più elegante di ottenere fattori come personaggi, ma qui è una versione modificata della funzione che le opere: df.real <- read.xlsx2("filename.xlsx", 1, colClasses=gsub("factor", "character", as.vector(sapply(df.temp, class)))).
Mikko

Funziona solo nella misura in cui il tipo di colonna può essere adeguatamente determinato dalla prima riga. Di solito si analizza più della prima riga per prendere quella decisione. La risposta potrebbe essere migliorata per rispondere al commento di aaa90210 nominando il pacchetto da cui provengono queste funzioni.
russellpierce

1

Un file Excel può essere letto direttamente in R come segue:

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

Lettura di file xls e xlxs utilizzando il pacchetto readxl

library("readxl")
my_data <- read_excel("xxxxx.xls")
my_data <- read_excel("xxxxx.xlsx")
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.