¿Cómo cargar (leer) una tabla de Excel en R?

Author

Cousteau Consultant Group

Published

January 8, 2024

Explora nuestros posts y nuestros cursos

Recuerda que tenemos diversos posts y dictamos cursos de programación, pesquerías, ecología, entre otros. Te invitamos a revisar la lista completa de nuestros posts en nuestra sección Posts y suscribirte a nuestras redes en Facebook y X para enterarte de nuestros cursos y de sus aperturas próximas.

R es un lenguaje de programación estadístico de uso general que se utiliza ampliamente en la ciencia de datos. Es un lenguaje potente y flexible que ofrece una amplia gama de funciones y paquetes para el análisis de datos.

Uno de los requisitos más comunes en ciencia de datos es la lectura de datos de fuentes externas, como archivos de texto, bases de datos o hojas de cálculo. En este artículo, veremos cómo leer archivos de Excel en R usando el paquete readxl, el cual admite archivos en formato .xls y .xlsx.

Instalación de readxl

readxl es un paquete oficial de CRAN, por lo que puede ser instalado a través del siguiente comando en consola de R:

install.packages("readxl")

¿Cómo leer un archivo de Excel a través de readxl?

La función que permite leer archivos de Excel y cargarlos a manera de objetos tbl (data.frame) es read_xlsx(). Esta función tiene dos argumentos principales:

  • path: la ruta al archivo de Excel que desea leer.
  • sheet: el nombre de la hoja de cálculo que desea leer a manera de texto entre comillas (de clase character). También es posible indicar el orden de la hoja a manera de un valor entero (de clase numeric o integer); sin embargo, se debe tener cuidado si se llega a modificar posteriormente el orden de las hojas del archivo Excel original.
Archivos de ejemplo

Los archivos utilizados en los artículos de Posts se encuentran alojados en nuestro repositorio de Github: https://github.com/CousteauG/posts-data.git.

Ejemplo 1: leyendo una hoja en un archivo

  • Iniciaremos descargando el archivo pesotalla_2010.xlsx

  • A continuación, cargaremos el paquete readxl y ejecutaremos la función read_xlsx haciendo referencia a la ruta en donde se aloja el archivo en nuestra PC.

require(readxl)

read_xlsx(path = "pesotalla_2010.xlsx", sheet = "enero")
# A tibble: 13 × 8
    year month   day  hour   min   sec weight length
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>  <dbl>
 1  2010     1     2     4    47    50   16.4   22.1
 2  2010     1     5    11    12    17 1260.    89.2
 3  2010     1     6    18    58    55  671     72.4
 4  2010     1     7    20    50     7    9.2   16.6
 5  2010     1    10    17     3     8  802.    76.8
 6  2010     1    12    23    18    37  611     70.3
 7  2010     1    12    17    15    13   19.5   22.3
 8  2010     1    15     5    33     2   53.2   31.1
 9  2010     1    16     7    59     7   36.8   27.6
10  2010     1    17    23    54    54   68.1   34.4
11  2010     1    20    15    48    38  408.    61.4
12  2010     1    23    18    43    32 1083.    84.9
13  2010     1    26    16    15    55    1.3    8.2

¡Excelente! ya hemos cargado nuestro primera tabla de Excel en R. Es importante recordar que readxl carga el archivo en un objeto de clase múltiple (tbl_df, tbl y data.frame), que hace que el modo en el que se representa en consola lo haga lucir algo distinto a un data.frame tradicional. Sin embargo, este objeto acepta cualquier operación válida para un data.frame.

Ejemplo 2: leyendo múltiples hojas en un mismo archivo

Nuestro archivo de ejemplo cuenta con 6 hojas y ante la necesidad de leer todas ellas podríamos estar tentados a repetir el comando anterior 6 veces cambiando el nombre de la hoja:

read_xlsx(path = "pesotalla_2010.xlsx", sheet = "enero") # Hoja 1
read_xlsx(path = "pesotalla_2010.xlsx", sheet = "febrero") # Hoja 2
read_xlsx(path = "pesotalla_2010.xlsx", sheet = "marzo") # Hoja 3
# ...
read_xlsx(path = "pesotalla_2010.xlsx", sheet = "junio") # Hoja 6

Sin embargo, este método resulta muy ineficiente a medidad que aumenta la cantidad de hojas en nuestro archivo, por lo que a continuación veremos una manera más rápida:

  • Utilizaremos la función excel_sheets del propio paquete readxl, que nos devuelve un vector con las hojas presentes en nuestro archivo de entrada y lo asignaremos a un objeto llamado hojas:
hojas <- excel_sheets(path = "pesotalla_2010.xlsx")

print(hojas)
[1] "enero"   "febrero" "marzo"   "abril"   "mayo"    "junio"  
  • Podemos notar que ya contamos con un vector sobre el que podemos iterar el comando de lectura ya aprendido. Sin embargo, hay varias formas de realizar esta iteración. La primera de ellas y la más intuitiva es aplicar un for (bucle) sobre nuestro vector hojas e ir almacenando cada tabla en un objeto llamado resultado_1:
# Método 1
resultado_1 <- list()
for(i in seq_along(hojas)){
  resultado_1[[i]] <- read_xlsx(path = "pesotalla_2010.xlsx", sheet = hojas[i])
}
La función seq_along

Esta función genera un vector con una secuencia de valores que van desde el 1 hasta la longitud de objeto dado como argumento. Por ejemplo, el objeto month.name contiene el nombre de los meses de año (por lo tanto, tiene 12 elementos):

month.name
 [1] "January"   "February"  "March"     "April"     "May"       "June"     
 [7] "July"      "August"    "September" "October"   "November"  "December" 
seq_along(month.name)
 [1]  1  2  3  4  5  6  7  8  9 10 11 12

Por la manera en cómo hemos desarrollado nuestro script, observamos que resultado_1 es un objeto de clase list.

class(resultado_1)
[1] "list"

Con seis elementos (uno para cada hoja leída).

length(resultado_1)
[1] 6

Y con la posibilidad de acceder a cada tabla a través de los típicos comandos de indexación de listas:

# Acceder a la tercera tabla
resultado_1[[3]]
# A tibble: 9 × 8
   year month   day  hour   min   sec weight length
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>  <dbl>
1  2010     3     3    14    14    47   84.2   36.8
2  2010     3     4     0    56    54   40.7   28.9
3  2010     3     5    19    29    59   66.3   33.5
4  2010     3     8    21     3    54   48.3   30.5
5  2010     3     9    19    40    15    3.3   11.8
6  2010     3    11     6    34     6 1283.    89.7
7  2010     3    17     0    32     1   21.6   23.7
8  2010     3    18     6    30    41    2      1.5
9  2010     3    23    23    49    27 1042.    83.8

Otro modo de realizar una lectura de todas las hojas es a través de la función lapply, que nos permite aplicar una función a lo largo de un vector y nos devuelve una lista en donde cada nivel representa el resultado de cada elemento del vector de entrada:

# Método 2
resultado_2 <- lapply(X = hojas, FUN = read_xlsx, path = "pesotalla_2010.xlsx")
class(resultado_2)
[1] "list"
length(resultado_2)
[1] 6
resultado_2[[3]]
# A tibble: 9 × 8
   year month   day  hour   min   sec weight length
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>  <dbl>
1  2010     3     3    14    14    47   84.2   36.8
2  2010     3     4     0    56    54   40.7   28.9
3  2010     3     5    19    29    59   66.3   33.5
4  2010     3     8    21     3    54   48.3   30.5
5  2010     3     9    19    40    15    3.3   11.8
6  2010     3    11     6    34     6 1283.    89.7
7  2010     3    17     0    32     1   21.6   23.7
8  2010     3    18     6    30    41    2      1.5
9  2010     3    23    23    49    27 1042.    83.8

Observamos que el resultado_2 es el mismo que resultado_1, pero tengamos en cuenta que solo hemos necesitado ejecutar una única línea de código.

Ejemplo 3: leyendo múltiples hojas desde múltiples archivos

En este caso, sí tendremos que hacer uso de un bucle (for) que corra a lo largo de cada archivo de interés.

  • El primer paso consistirá en crear un vector con las rutas de los archivos que nos interesa leer. Para ello, utilizaremos como ejemplo los archivos pesotalla_ contenidos en el repositorio de Github link:
# Crear un vector con las rutas de los archivos de interés
archivos <- c("pesotalla_2010.xlsx", "pesotalla_2012.xlsx")
¿Qué hacer si tengo muchos archivos con un mismo patrón de nombre?

En R hay diversas formas de armar un vector en donde haya repetición de un determinado patrón de texto. Es posible utilizar la función paste (o paste0 si se desea que no haya separación entre las uniones):

paste("pesotalla_", 2010:2015, ".xlsx", sep = "")
[1] "pesotalla_2010.xlsx" "pesotalla_2011.xlsx" "pesotalla_2012.xlsx"
[4] "pesotalla_2013.xlsx" "pesotalla_2014.xlsx" "pesotalla_2015.xlsx"
paste0("pesotalla_", 2010:2015, ".xlsx")
[1] "pesotalla_2010.xlsx" "pesotalla_2011.xlsx" "pesotalla_2012.xlsx"
[4] "pesotalla_2013.xlsx" "pesotalla_2014.xlsx" "pesotalla_2015.xlsx"

Así mismo, si nuestro patrón de nombre es algo más complejo, podemos utilizar la función sprintf.

sprintf("pesotalla_%s.xlsx", 2010:2015)
[1] "pesotalla_2010.xlsx" "pesotalla_2011.xlsx" "pesotalla_2012.xlsx"
[4] "pesotalla_2013.xlsx" "pesotalla_2014.xlsx" "pesotalla_2015.xlsx"
  • A continuación, utilizaremos el vector archivos para generar un bucle e iremos guardando los resultados en un objeto llamado resultado_3:
resultado_3 <- list()
for(i in seq_along(archivos)){
  # Obtener el nombre de las hojas en cada archivo
  hojas <- excel_sheets(path = archivos[i])
  
  # Leer hojas y guardar almacenar los resultados 
  resultado_3[[i]] <- lapply(X = hojas, FUN = read_xlsx, path = archivos[i])
}

Concatenando tablas desde listas

Genial, hasta ahora, hemos visto cómo leer y cargar los datos desde archivos-hojas de Excel hacia tablas independientes en R. En los dos ejemplos anteriores, hemos logrado obtener listas en donde cada elemento contiene las tablas leídas. A continuación, veremos cómo concatenar estas tablas en un solo objeto a través de la función bind_rows del paquete dplyr.

Concatenando tablas de resultado_2 (Ejemplo 2)

  • Cargamos el paquete dplyr
require(dplyr)
  • Ejecutamos la función bind_rows.
resultado_2_all <- bind_rows(resultado_2)

print(resultado_2_all)
# A tibble: 77 × 8
    year month   day  hour   min   sec weight length
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>  <dbl>
 1  2010     1     2     4    47    50   16.4   22.1
 2  2010     1     5    11    12    17 1260.    89.2
 3  2010     1     6    18    58    55  671     72.4
 4  2010     1     7    20    50     7    9.2   16.6
 5  2010     1    10    17     3     8  802.    76.8
 6  2010     1    12    23    18    37  611     70.3
 7  2010     1    12    17    15    13   19.5   22.3
 8  2010     1    15     5    33     2   53.2   31.1
 9  2010     1    16     7    59     7   36.8   27.6
10  2010     1    17    23    54    54   68.1   34.4
# ℹ 67 more rows

Podemos ver que el resultado es una tabla de 77 filas que contiene la información de todos de enero a junio. Lo podemos comprobar solicitando la cantidad de filas para cada valor de mes (variable month):

table(resultado_2_all$month)

 1  2  3  4  5  6 
13 12  9 14 14 15 

¿Eso es todo? Sí, la función bind_rows es muy práctica y se ocupa de detectar qué columnas en común existen en los objetos de entrada y de concatenar coherentemente.

Concatenando tablas de resultado_3 (Ejemplo 3)

Para este caso, utilizaremos dos etapas: en la primera, aplicaremos bind_rows a cada nivel de nuestra lista (que contenía las tablas de cada archivo) a través de la función lapply y luego, en la segunda etapa, combinaremos las tablas obtenidas en una única tabla:

resultado_3_all <- lapply(resultado_3, bind_rows) # etapa 1
resultado_3_all <- bind_rows(resultado_3_all) # etapa 2

print(resultado_3_all)
# A tibble: 155 × 8
    year month   day  hour   min   sec weight length
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>  <dbl>
 1  2010     1     2     4    47    50   16.4   22.1
 2  2010     1     5    11    12    17 1260.    89.2
 3  2010     1     6    18    58    55  671     72.4
 4  2010     1     7    20    50     7    9.2   16.6
 5  2010     1    10    17     3     8  802.    76.8
 6  2010     1    12    23    18    37  611     70.3
 7  2010     1    12    17    15    13   19.5   22.3
 8  2010     1    15     5    33     2   53.2   31.1
 9  2010     1    16     7    59     7   36.8   27.6
10  2010     1    17    23    54    54   68.1   34.4
# ℹ 145 more rows

Se observa que la tabla final contiene 155 filas y podemos revisar los resultados solicitando un conteo del número de filas por cada mes-año.

table(resultado_3_all$year, resultado_3_all$month)
      
        1  2  3  4  5  6
  2010 13 12  9 14 14 15
  2012 17 12  6 11 23  9
¿Qué más puedo hacer con read_xlsx?

read_xlsx es muy versátil y nos permite modificar múltiples parámetros a través de sus varios argumentos, como por ejemplo el rango de celdas que queremos leer (por defecto, leerá todo el contenido de una hoja), el número de filas que podemos omitir en la lectura, la clase asignada a cada columna leída, el tipo de caracter que será considerado como NA, entre otros. El detalle de todos los argumentos relacionados los podemos encontrar en la documentación ejecutando ?read_xlsx.