Visualiza tus datos en R con ggplot2 y gganimate

Una gráfica es una buena manera de expresar los datos, estos ayudan a ver detalles que simplemente pueden pasar desapercibidos cuando sólo se los analizan numericamente, estos pueden tener aún mayor impacto si estan animados. ¿Por qué no hacerlo?. En este artículo se describe como hacer animación usando ggplot2 y gganimate en R.
Comenzando
Usamos R por ser un lenguaje especializado para ciencia de datos y tener una gran Comunidad Open Source. Antes de comenzar recomendamos tener las versiones actualizadas de R y su IDE RStudio.
Puedes descargar R y RStudio desde sus páginas web oficiales:
Instalación de pre-requisitos
Para este ejemplo usamos las bibliotecas de rio
, dplyr
, ggplot2
y gganimate
. Las instalamos con los siguientes comandos en R
(Recuerde que para ejecutar una linea de Comando en el Editor de RStudio Es con Ctrl+Enter o puede escribirlo directamento en la Consola)
1install.package(rio) # Biblioteca para importar archivos csv o xlsx
2install.package(dplyr) # Biblioteca para filtrar datos
3install.package(ggplot2) # Biblioteca para realizar las gráficas
4install.package(gganimate) # Biblioteca para realizar la animación
Preparación de los datos para graficar
Los datos usados pertenecen a la base de datos del INE (Instituto Nacional de Estadística Bolivia), el archivo usado tiene el nombre de "Importaciones de Productos y Artículos de Bolivia 1992-2021p"
Abrimos nuestras bibliotecas:
1library(rio)
2library(ggplot2)
3library(gganimate)
4library(dplyr)
Importamos los datos a un objeto llamado libro
con:
1libro <- import(".my/path/DatosImportacionBolivia1992-2021.csv")
Para ver la cabecera del libro, y para ver la estructura del libro
ejecutamos respectivamente head(libro)
y str(libro)
.
1> head(libro)
2 Fecha ALIMENTOS Y BEBIDAS SUMINISTROS INDUSTRIALES COMBUSTIBLES Y LUBRICANTES
31 1992-01-01 12.686477 30.38827 1.738607
42 1992-02-01 9.139570 32.57593 1.822906
53 1992-03-01 6.150201 21.37546 2.000110
64 1992-04-01 9.225652 28.34524 1.455245
75 1992-05-01 14.503611 22.06801 2.168646
86 1992-06-01 5.875804 25.43617 3.084602
9 BIENES DE CAPITAL EQUIPO DE TRANSPORTE Y SUS PIEZAS Y ACCESORIOS ARTÍCULOS DE CONSUMO
101 25.66374 22.20454 5.585219
112 22.00027 18.68626 6.528652
123 22.92478 17.40578 6.196415
134 31.14429 16.77957 5.422824
145 26.82719 22.79343 5.458318
156 23.47011 16.00698 5.647866_
1> str(libro)
2'data.frame': 358 obs. of 7 variables:
3 $ Fecha : IDate, format: "1992-01-01" "1992-02-01" ...
4 $ ALIMENTOS Y BEBIDAS : num 12.69 9.14 6.15 9.23 14.5 ...
5 $ SUMINISTROS INDUSTRIALES : num 30.4 32.6 21.4 28.3 22.1 ...
6 $ COMBUSTIBLES Y LUBRICANTES : num 1.74 1.82 2 1.46 2.17 ...
7 $ BIENES DE CAPITAL : num 25.7 22 22.9 31.1 26.8 ...
8 $ EQUIPO DE TRANSPORTE Y SUS PIEZAS Y ACCESORIOS: num 22.2 18.7 17.4 16.8 22.8 ...
9 $ ARTÍCULOS DE CONSUMO : num 5.59 6.53 6.2 5.42 5.46 ...
Es importante verificar el tipo de dato, antes de graficar, en este caso nos importa que la fecha tenga formato de IDate
y los demás sean tengan formato de num
. En caso de que la fecha no tenga formato IDate
puedo tranformar la columna usando la el comando columna<-as.Date(columna)
.
Con las siguientes líneas de código, compactamos el número de columnas de nuestro libro
en un nuevo objeto llamado datos
. (Notese que solamente utilizaremos las primeras 4 columnas del objeto libro). Es decir una columna para la fecha, una columna para su valor y otra columna que muestre su clasificación.
1# Simplificando nuestra tabla para realizar las gráficas
2# Cuando se escribe el nombre del objeto libro$.. en RStudio el autocomplado con los nombres de la columnas del libro
3datos <-
4 data.frame(
5 Fecha = c(libro$Fecha, libro$Fecha, libro$Fecha, libro$Fecha),
6 Valor = c(
7 libro$`ALIMENTOS Y BEBIDAS`,
8 libro$`SUMINISTROS INDUSTRIALES`,
9 libro$`COMBUSTIBLES Y LUBRICANTES`,
10 libro$`EQUIPO DE TRANSPORTE Y SUS PIEZAS Y ACCESORIOS`
11 ),
12 Clasificacion = c(
13 rep("Alimentos y Bebidas", nrow(libro)),
14 rep("Suministros Industriales", nrow(libro)),
15 rep("Combustibles y Lubricantes", nrow(libro)),
16 rep("Equipo de Transporte", nrow(libro)
17 )
Funciones auxiliares usadas:
libro$columna
: para acceder alcolumna
dellibro
.data.frame(columna1, columna2 ...)
: para crear una nuevoobjeto de Datos
.c(elemento1, elemento2, ...)
: para juntarelementos
en un vector.rep(elemento, n_veces)
: para generar un vector con elelemento
repetidon_veces
.nrow(tabla)
: para obtener el número de filas de tabla.
Observemos la cabecera de datos
para verificar, con head(datos)
:
1> head(datos)
2 Fecha Valor Clasificacion
31 2018-01-01 56.34888 Alimentos y Bebidas
42 2018-02-01 47.42231 Alimentos y Bebidas
53 2018-03-01 59.54501 Alimentos y Bebidas
64 2018-04-01 56.08808 Alimentos y Bebidas
75 2018-05-01 51.86330 Alimentos y Bebidas
86 2018-06-01 43.84668 Alimentos y Bebidas
Gráfica estática
Para graficar con ggplot2
, es conveniente entender que esta biblioteca añade sus componentes en layers (capas), estos layers son objetos a los cuales se le puede modificar su apariencia y especificar de donde extraer sus valores.
Asignamos a un objeto ggplot llamado p1 lo que vamos a graficar:
1# Modificando el theme a uno con el fondo blanco
2theme_set(theme_bw())
3
4p1 <- ggplot(data = datos) +
5 geom_line(aes(x = Fecha, y = Valor, color = Clasificacion), size = 0.5) +
6 theme(legend.position = "right") +
7 labs(
8 x = "Fecha",
9 y = "Valor en MM Bs",
10 color = "",
11 title = "Datos de Importación de Bolivia 1991-2021p",
12 subtitle = "Expresado en Millones de Bolivianos"
13 )
14p1
Funciones utilizadas
theme_set(theme_bw())
: modifica el conjunto de colores usado en el tema para realizar la gráfica.ggplot(data)
: esta es la primera capa a utilizarse inicialmente le asignamos nuestos datosdata
para que cree las dimensiones de las coordenadas y esta se herede a las otras capas.geom_line(aes(x, y, color), size)
: capa que hereda los datos deggplot()
, se los puede usar directamente con el nombre de sus columnas, grafica los datosx
ey
como líneas, las clasifica de acuerdo alcolor
ysize
determina el grosor de sus líneas.theme(legend.position)
: capa que modifica la posición de la leyenda dentro gráfico, conlegend.position
, esta puede adquirir valores detop
,left
, etc.labs(x, y, color, title, subtitle)
: capa que pone los nombres a ejex
y al ejey
, además de poner el nombre encima de las leyendas concolor
, el nombre título y subtítulo contitle
ysubtitle
respectivamente.
Gráfica Animada
Ya teniendo nuestra nuestra gráfica estática, vamos a realizar algunas modificaciones para que se resalten los datos de nuestro interés.
Filtrando datos con fecha mayor al año 2019.
1datos <- filter(datos, datos$Fecha >= as.Date("2019-01-01"))
filter(datos, condicion)
: evalua cada fila dedatos
y filtra de acuerdo a lacondicion
.as.Date(var)
conviertevar
a un formato de fechaIDate
Agregando un nuevo data frame periodos para resaltar las fechas de confinamiento por Covid19.
1periodos <-
2 data.frame(
3 xmin = as.Date("2020-03-22"),
4 xmax = as.Date("2020-08-31"),
5 ymin = -Inf,
6 ymax = Inf,
7 Periodo = "Confinamiento por COVID19"
8 )
Creando un nuevo objeto ggplot2
p2 para incluir las nuevas modificaciones.
1p2 <- ggplot(data = datos) +
2 geom_line(aes(x = Fecha, y = Valor, color = Clasificacion), size = 1) +
3 geom_rect(
4 data = periodos,
5 alpha = 0.2,
6 aes(
7 xmin = xmin,
8 xmax = xmax,
9 ymin = ymin,
10 ymax = ymax,
11 fill = Periodo
12 )
13 ) +
14 theme(legend.position = "right") +
15 labs(
16 x = "Fecha",
17 y = "Valor en MM Bs",
18 color = "" ,
19 fill = "",
20 title = "Datos de Importación Bolivia 2019-2021p",
21 subtitle = "Expresado en Millones de Bolivianos"
22 )
23p2
geom_rect(data, alpha, aes(xmin, xmax, ymin, ymax, fill))
: dibuja un rectangulo a partir de los datos enData
, modifica su opacidad de acuerdo aalpha
, extrae los datos de acuerdo axmin, xmax, ymin, ymax
, y los clasifica de acuerdo afill
.lab(fill)
: pone el nombre encima de la leyenda de los datos clasificados confill
.
Con las modificaciones ya hechas en p2, creamos el objeto gganimate
llamado anim
el cuál contendrá nuestra grafico a animar.
1anim <- p2 + transition_reveal(Fecha) +
2 geom_label(aes(
3 x = as.Date("2019-06-01"),
4 y = 280,
5 label = format(datos$Fecha, "%Y")
6 ),
7 col = "gray",
8 size = 15)
transition_reveal(var)
: añade la capa de animacion del tipo transición usando como referencia la variablevar
.geom_label((aes(x,y,label)) col, size)
: añade la capa de etiquetas del año dentro de la gráfica, conaes(x, y, label)
:x
ey
son las coordenadas donde se grafica la etiquetalabel
, concol
seleccionamos un color y consize
el tamaño.
Nota: geom_label() fué diseñado para graficar etiquetas que acompañen a la gráfica. En este ejemplo en específico fué usado como una etiqueta estática fijando sus coordenadas x
e y
en un sólo punto. Se optó por esta opción ya que genera un buen impacto visual.
Con el objeto anim
creado podemos invocar la función animate()
de gganimate
. Una vez ejecutada la función se abrirá una ventana con el resultado en formato .gif.
1animate(
2 anim,
3 fps = 25,
4 duration = 15,
5 width = 800,
6 height = 500,
7 end_pause = 30
8)
animate(anim, fps, duration, width, height, end_pause)
:animate()
funcion para generar la animación,anim
objeto a animarse,fps
cantidad de frames por segundo,duration
duración de la animación en segundos,with
,height
ancho y alto de la animación respectivamente en pixeles,end_pause
cantidad de veces a repetirse el último frame para la animación.
Hay casos en los que extrañamente no se instalan los renders para hacer la renderización de la animación y aparece un error al tratar de ejecutar el código arriba mostrado, en ese caso puede probar con la siguiente solución: Ejecute en modo administrador RStudio e instale los renders con install.packages("gifski")
para el render que viene por defecto con gganimate
, tambien puede instalar el render magick con install.packages("magick")
para tener otra opción para renderizar. Para saber que opciones tiene el render magick ejecute help("magick_renderer")
y se le mostrara su breve manual.
Despues de ver la animación podemos guardarla haciendo:
1archivo <-
2 animate(
3 anim,
4 fps = 25,
5 duration = 15,
6 width = 800,
7 height = 500,
8 end_pause = 30
9 )
10
11anim_save(filename = "datosimportpandemia.gif",
12 animation = archivo,
13 path = ".my/path/save/")
anim_save(filename, animation, path)
:
guarda el renderizado de animation
con el nombre filename
en la ruta path
.