Leer un archivo de Excel directamente desde un script R

95

¿Cómo puedo leer un archivo de Excel directamente en R? ¿O debería exportar primero los datos a un archivo de texto o CSV e importar ese archivo a R?

vadeadores
fuente
@Sacha Epskamp: con xlsReadWrite, ni siquiera necesita instalar Perl.
Joris Meys
1
gdatala versión 2.8.2 lee xlsxarchivos con la read.xlsfunción
Ben
1
Vea mi advertencia (como respuesta a continuación) con respecto a la posible pérdida de precisión si exporta los datos a un formato de texto desde Excel.
russellpierce
1
xlsxpaquete para xlsx / xlsm / xls, no sé sobre xlam, etc.
Qbik
2
"Nunca veo una razón para no exportar primero a un archivo de texto". Qué tal esto: cuando exporto a CSV, uno de los campos que necesito no se escribe. Parece una especie de DRM, pero como no escribí la hoja de cálculo, no lo sé.
Nate Reed

Respuestas:

41

Si. Consulte la página correspondiente en R wiki . Respuesta corta: read.xlsel gdatapaquete funciona la mayor parte del tiempo (aunque debe tener Perl instalado en su sistema, generalmente ya es cierto en MacOS y Linux, pero da un paso adicional en Windows, es decir, consulte http://strawberryperl.com/ ). Hay varias advertencias y alternativas enumeradas en la página wiki de R.

La única razón que veo para no hacer esto directamente es que es posible que desee examinar la hoja de cálculo para ver si tiene fallas (encabezados extraños, varias hojas de trabajo [solo puede leer una a la vez, aunque obviamente puede recorrerlas todas]) , parcelas incluidas, etc.). Pero para una hoja de cálculo rectangular bien formada con números simples y datos de caracteres (es decir, números sin formato de coma, fechas, fórmulas con errores de división por cero, valores faltantes, etc., etc.), generalmente no tengo ningún problema con este proceso.

Ben Bolker
fuente
6
Hay muchos problemas potenciales a considerar que me he encontrado personalmente. Los campos con números con comas deben eliminarse y convertirse en numéricos en R. Los campos con "-" deben recodificarse a NA. La recomendación general es mirar realmente sus números en Excel y asegurarse de que se traduzcan correctamente a R.
Brandon Bertelsen
3
No puedo discutir con "realmente necesitas mirar tus números" ... ¿cuál es el problema con los campos "-"? no na.strings="-"abordar el problema? ¿Cuántos de estos problemas son genéricos y cuántos de ellos (por ejemplo, campos numéricos con comas) se pueden abordar con otras herramientas como XLConnect ...?
Ben Bolker
1
Ese comentario fue dirigido al OP, no a ti Ben, culpa mía por una mala colocación.
Brandon Bertelsen
1
Anécdota relevante: read.xlstener éxito en la lectura de una hoja muy grande de un archivo de Excel donde ambos XLConnecty xlsxno (creo porque ambos se basan en Apache POI )
Matt Parker
49

Permítanme reiterar lo que @Chase recomendó: use XLConnect .

Las razones para usar XLConnect son, en mi opinión:

  1. Plataforma cruzada. XLConnect está escrito en Java y, por lo tanto, se ejecutará en Win, Linux, Mac sin cambios en su código R (excepto posiblemente cadenas de ruta)
  2. Nada más para cargar. Simplemente instale XLConnect y continúe con su vida.
  3. Solo mencionó leer archivos de Excel, pero XLConnect también escribirá archivos de Excel, incluido el cambio de formato de celda. Y lo hará desde Linux o Mac, no solo desde Win.

XLConnect es algo nuevo en comparación con otras soluciones, por lo que se menciona con menos frecuencia en publicaciones de blogs y documentos de referencia. Para mi ha sido muy útil.

JD Long
fuente
48

Y ahora hay readxl :

El paquete readxl facilita la obtención de datos de Excel y de R. En comparación con los paquetes existentes (por ejemplo, gdata, xlsx, xlsReadWrite, etc.), readxl no tiene dependencias externas, por lo que es fácil de instalar y usar en todos los sistemas operativos. Está diseñado para trabajar con datos tabulares almacenados en una sola hoja.

readxl está construido sobre la biblioteca libxls C, que abstrae muchas de las complejidades del formato binario subyacente.

Es compatible con el formato .xls heredado y .xlsx

readxl está disponible en CRAN, o puede instalarlo desde github con:

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

Uso

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

Tenga en cuenta que, si bien la descripción dice 'sin dependencias externas', sí requiere el Rcpppaquete , que a su vez requiere Rtools (para Windows) o Xcode (para OSX), que son dependencias externas a R. Aunque muchas personas las tienen instaladas por otras razones .

Ben
fuente
3
Mucho más rápido que xlsx. El tiempo de lectura es como read.xlsx2, pero infiere tipos.
Steve Rowe
1
@SteveRowe ve una nueva respuesta para algunos puntos de referencia objetivos (intentados) que confirman esto
MichaelChirico
¿Hay alguna forma de leer cadenas como factores usando read_excel? Me gusta la velocidad en comparación con read.xlsx, pero tener que convertir manualmente las columnas de caracteres a factores frustra el propósito.
coip
2
+1 por el hecho de que no tiene dependencias. Odio tener que instalar java. Y lo he probado y me funciona muy bien.
Bastian
2
readxl y openxlsx son los mejores. readxl es más rápido pero no permite escribir. De todos modos, ninguno de ellos funciona bien cuando se intenta especificar clases / tipos de columna.
skan
29

EDITAR 2015-Octubre: Como otros han comentado aquí, los paquetes openxlsxy readxlson mucho más rápidos que el xlsxpaquete y en realidad logran abrir archivos de Excel más grandes (> 1500 filas y> 120 columnas). @MichaelChirico demuestra que readxles mejor cuando se prefiere la velocidad y openxlsxreemplaza la funcionalidad proporcionada por el xlsxpaquete. Si está buscando un paquete para leer, escribir y modificar archivos de Excel en 2015, elija el en openxlsxlugar de xlsx.

Antes de 2015: he usado xlsxpackage . Cambió mi flujo de trabajo con Excel y R. No más molestas ventanas emergentes preguntando si estoy seguro de que quiero guardar mi hoja de Excel en formato .txt. El paquete también escribe archivos de Excel.

Sin embargo, encuentro que la read.xlsxfunción es lenta cuando abro archivos grandes de Excel. read.xlsx2La función es considerablemente más rápida, pero no consulta la clase vectorial de columnas data.frame. Debe usar el colClassescomando para especificar las clases de columna deseadas, si usa la read.xlsx2función. He aquí un ejemplo práctico:

read.xlsx("filename.xlsx", 1)lee su archivo y hace que las clases de columna data.frame sean casi útiles, pero es muy lento para grandes conjuntos de datos. Funciona también para .xlsarchivos.

read.xlsx2("filename.xlsx", 1)es más rápido, pero tendrá que definir clases de columna manualmente. Un atajo es ejecutar el comando dos veces (vea el ejemplo a continuación). characterLa especificación convierte sus columnas en factores. Uso Datey POSIXctopciones de tiempo.

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
fuente
25

Dada la proliferación de diferentes formas de leer un archivo de Excel Ry la gran cantidad de respuestas aquí, pensé en intentar aclarar cuál de las opciones mencionadas aquí funciona mejor (en algunas situaciones simples).

Yo mismo he estado usando xlsxdesde que comencé a usar R, por inercia al menos, y recientemente noté que no parece haber ninguna información objetiva sobre qué paquete funciona mejor.

Cualquier ejercicio de evaluación comparativa está plagado de dificultades, ya que algunos paquetes seguramente manejarán ciertas situaciones mejor que otros, y una cascada de otras advertencias.

Dicho esto, estoy usando un conjunto de datos (reproducible) que creo que está en un formato bastante común (8 campos de cadena, 3 numéricos, 1 entero, 3 fechas):

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

Entonces escribí esto a csv y abierto en LibreOffice y se guarda como un archivo .xlsx, a continuación, comparó 4 de los paquetes mencionados en este hilo: xlsx, openxlsx, readxl, y gdata, usando las opciones por defecto (también probé una versión de si o no, especificar tipos de columna, pero esto no cambió la clasificación).

Estoy excluyendo RODBCporque estoy en Linux; XLConnectporque parece que su propósito principal no es leer en hojas individuales de Excel, sino importar libros de Excel completos, por lo que poner su caballo en la carrera solo con sus capacidades de lectura parece injusto; y xlsReadWriteporque ya no es compatible con mi versión de R(parece haber sido eliminado).

Luego ejecuté puntos de referencia con NN=1000Ly NN=25000L(restableciendo la semilla antes de cada declaración de lo data.frameanterior) para permitir diferencias con respecto al tamaño del archivo de Excel. gces principalmente para xlsxlo que he descubierto que a veces puede crear obstrucciones en la memoria. Sin más preámbulos, aquí están los resultados que encontré:

Archivo Excel de 1000 filas

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

También lo readxles el ganador, con openxlsxcompetitivo y gdataun claro perdedor. Tomando cada medida relativa al mínimo de la columna:

#       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 mi propio favorito, xlsxes 60% más lento que readxl.

Archivo Excel de 25.000 filas

Debido a la cantidad de tiempo que lleva, solo hice 20 repeticiones en el archivo más grande; de ​​lo contrario, los comandos eran idénticos. Aquí están los datos sin procesar:

# 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

Aquí están los datos 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

También lo readxles el claro ganador cuando se trata de velocidad. gdataEs mejor tener algo más a su favor, ya que es dolorosamente lento leer archivos de Excel, y este problema solo se agrava para tablas más grandes.

Dos de las características openxlsxson 1) sus otros métodos extensos ( readxlestá diseñado para hacer solo una cosa, que probablemente sea parte de por qué es tan rápido), especialmente su write.xlsxfunción, y 2) (más un inconveniente para readxl) el col_typesargumento en readxlsolo (como de este escrito) acepta algunos no estándar R: en "text"lugar de "character"y en "date"lugar de "Date".

MichaelChirico
fuente
Sería genial si también agrega el punto de referencia para XLConnect. También comente que readxl no puede escribir. xlsx y openxlsx no funcionan correctamente con la opción col_types o colClasses.
skan
@skan Inicialmente ejecuté algunas pruebas XLConnectpero es muy lento; Creo que readxllos inconvenientes fueron cubiertos suficientemente en mi párrafo final; y no tengo una experiencia similar a la suya con xlsxo openxlsxcomo utilizo habitualmente ambos para especificar tipos.
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, me gusta RODBC y puedo recomendarlo.

Brandon Bertelsen
fuente
7
Advertencia: ODBC a veces puede ser complicado de ejecutar en plataformas distintas de Windows.
JD Long
1
@JD Long e incluso en Windows es un PITA. No hay tiempo sexy para mí y ODBC en W7 de 64 bits ...
Roman Luštrik
4
Cargando el paquete requerido: Error RODBC en odbcConnectExcel (file.name): odbcConnectExcel solo se puede usar con Windows de 32 bits
andrekos
6

Otra solución es el xlsReadWritepaquete, que no requiere instalaciones adicionales, pero requiere que descargue el shlib adicional antes de usarlo por primera vez al:

require(xlsReadWrite)
xls.getshlib()

Olvidar esto puede causar una frustración total. He estado allí y todo eso ...

En una nota al margen: es posible que desee considerar la conversión a un formato basado en texto (por ejemplo, csv) y leer desde allí. Esto por varias razones:

  • Cualquiera que sea su solución (RODBC, gdata, xlsReadWrite) pueden suceder cosas extrañas cuando sus datos se convierten. Especialmente las fechas pueden ser bastante engorrosas. El HFWutilspaquete tiene algunas herramientas para lidiar con fechas EXCEL (según el comentario de @Ben Bolker).

  • si tiene hojas grandes, leer archivos de texto es más rápido que leer desde EXCEL.

  • para archivos .xls y .xlsx, pueden ser necesarias diferentes soluciones. Por ejemplo, el paquete xlsReadWrite actualmente no es compatible con .xlsx AFAIK. gdatarequiere que instale bibliotecas de perl adicionales para la compatibilidad con .xlsx. xlsxEl paquete puede manejar extensiones del mismo nombre.

Joris Meys
fuente
@Ben Thx por el consejo, lo incluiré en mi respuesta. Sin embargo, no intenté estar completo, ya que la página wiki a la que los enlaces de respuesta aceptados ya está bastante completa. Pero no menciona el paquete HFWutils.
Joris Meys
1
-1; Mira mi respuesta. TL: DR: Excel no guarda un conjunto de datos de precisión completo en csv (o en el portapapeles). Solo se conservan los valores visibles.
russellpierce
5

Como se señaló anteriormente en muchas de las otras respuestas, hay muchos paquetes buenos que se conectan al archivo XLS / X y obtienen los datos de una manera razonable. Sin embargo, se le debe advertir que bajo ninguna circunstancia debe utilizar el archivo del portapapeles (o un archivo .csv) para recuperar datos de Excel. Para ver por qué, ingrese =1/3a una celda en Excel. Ahora, reduzca el número de puntos decimales visibles a dos. Luego copie y pegue los datos en R. Ahora guarde el CSV. Notarás que en ambos casos Excel ha conservado de manera útil solo los datos que eran visibles para ti a través de la interfaz y has perdido toda la precisión en tus datos de origen reales.

Russellpierce
fuente
1
Me encantaría saber quién pensó que la fidelidad numérica no era relevante / importante.
russellpierce
1
Buen aviso. Sin embargo, depende del paquete que utilice. algunos no caen en esta trampa.
RockScience
@RocketScience Esta es una elección de diseño fundamental en la exportación CSV de Excel. ¿Tiene un ejemplo de un paquete que usa el portapapeles que no tiene este problema? Los paquetes que analizan directamente el archivo xls xlsx tienden a no caer en esta trampa. Por lo tanto, el alcance específico de mi advertencia.
russellpierce
en Unix puedes probar gnumeric::read.gnumeric.sheet. En Windows no estoy 100% seguro, pero creo gdata::read.xlsque también debería funcionar bien (aunque es necesario instalar Perl)
RockScience
@RockScience Respetuosamente, gdata :: read.xls no opera en los datos del portapapeles (a menos que se desvíe de su camino) y gnumeric no es Excel. Entonces, en ausencia de pruebas extraordinarias, mi advertencia permanece. Hay muchas otras buenas opciones en respuesta a esta pregunta; esperemos que la gente las use en su lugar.
russellpierce
5

Ampliando la respuesta proporcionada por @Mikko, puede usar un truco ingenioso para acelerar las cosas sin tener que "conocer" las clases de sus columnas de antemano. Simplemente use read.xlsxpara tomar un número limitado de registros para determinar las clases y luego continúe conread.xlsx2

Ejemplo

# 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
fuente
1
Su solución vuelve numerica factorsen mi equipo. read.xlsxutiliza characteren readColumnsfunción para especificar factores. Estoy seguro de que es una forma más elegante de conseguir factores como personajes, pero aquí es una versión modificada de la función que las obras: df.real <- read.xlsx2("filename.xlsx", 1, colClasses=gsub("factor", "character", as.vector(sapply(df.temp, class)))).
Mikko
Esto solo funciona en la medida en que el tipo de columna pueda determinarse adecuadamente mediante la primera fila. Por lo general, se analiza más que la primera fila para tomar esa determinación. La respuesta podría mejorarse para abordar el comentario de aaa90210 nombrando el paquete del que provienen estas funciones.
russellpierce
1

Un archivo de Excel se puede leer directamente en R de la siguiente manera:

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

Lectura de archivos xls y xlxs usando el paquete readxl

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