install.packages("readxl")
¿Cómo cargar (leer) una tabla de Excel en R?
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:
¿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 clasecharacter
). También es posible indicar el orden de la hoja a manera de un valor entero (de clasenumeric
ointeger
); sin embargo, se debe tener cuidado si se llega a modificar posteriormente el orden de las hojas del archivo Excel original.
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 llamadohojas
:
<- excel_sheets(path = "pesotalla_2010.xlsx")
hojas
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 llamadoresultado_1
:
# Método 1
<- list()
resultado_1 for(i in seq_along(hojas)){
<- read_xlsx(path = "pesotalla_2010.xlsx", sheet = hojas[i])
resultado_1[[i]] }
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
3]] resultado_1[[
# 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
<- lapply(X = hojas, FUN = read_xlsx, path = "pesotalla_2010.xlsx")
resultado_2 class(resultado_2)
[1] "list"
length(resultado_2)
[1] 6
3]] resultado_2[[
# 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
<- c("pesotalla_2010.xlsx", "pesotalla_2012.xlsx") archivos
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 llamadoresultado_3
:
<- list()
resultado_3 for(i in seq_along(archivos)){
# Obtener el nombre de las hojas en cada archivo
<- excel_sheets(path = archivos[i])
hojas
# Leer hojas y guardar almacenar los resultados
<- lapply(X = hojas, FUN = read_xlsx, path = archivos[i])
resultado_3[[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
.
<- bind_rows(resultado_2)
resultado_2_all
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:
<- lapply(resultado_3, bind_rows) # etapa 1
resultado_3_all <- bind_rows(resultado_3_all) # etapa 2
resultado_3_all
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
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
.