Cómo crear animaciones en R con gganimate

Share on linkedin
Share on twitter
Share on email

Un gráfico es una buena forma de representar nuestros datos, sin embargo hay veces que no son tan impactantes o, incluso, que no permiten ver cómo ha sido la evolución de un proceso. Por suerte, con animaciones podemos crear impacto, mostrar la evolución de procesos y mucho más, pero… ¿sabes cómo crearlos? En este post te explico cómo crear animaciones en R con gganimate para poder llevar tus gráficos al siguiente nivel. ¿Te suena bien? ¡Pues vamos a ello!

Cómo crear crear animaciones en R con gganimate

Preparar los datos para poder hacer la animación con gganimate

Al igual que cuando hacemos un gráfico con ggplot2, lo primero que necesitamos para crear animaciones en R con gganimate es que nuestros datos tengan la forma necesaria para poder dibujarlos correctamente.

Como casi siempre a la hora de graficar, necesitaremos que los datos tengan una estructura tidy , es decir, los datos cumplan los siguientes tres puntos:

  1. Cada columna debe ser una variable.
  2. Todas las filan deben referirse a una observación.
  3. Cada celda debe contener un único valor.

En nuestro caso usaremos el dataset gapminder, al ser un clásico de las animaciones.

library(gapminder)
datos = gapminder
head(datos)
## # A tibble: 6 x 6
##   country     continent  year lifeExp      pop gdpPercap
##   <fct>       <fct>     <int>   <dbl>    <int>     <dbl>
## 1 Afghanistan Asia       1952    28.8  8425333      779.
## 2 Afghanistan Asia       1957    30.3  9240934      821.
## 3 Afghanistan Asia       1962    32.0 10267083      853.
## 4 Afghanistan Asia       1967    34.0 11537966      836.
## 5 Afghanistan Asia       1972    36.1 13079460      740.
## 6 Afghanistan Asia       1977    38.4 14880372      786.

Si tus datos no están en formato tidy, seguramente las librerías dplyr y tidyr te ayudarán a conseguirlo. Te dejo por aquí su cheatsheet.

Una vez tenemos los datos en formato tidy, ya estamos listos para crear animaciones en R con gganimate.

Creando animaciones en R

Para crear la animación empezaremos creando un gráfico de ggplot normal. Si tienes muchos datos que superpuestos quedan feos, puedes filtrar los gráficos para verlos sobre un estado (en nuestro caso el año). Al fin y al cabo, el objetivo de crear el gráfico es que mostremos los datos de una forma que nos gustan y resulten atractivos para después crear la animación sobre eso.

library(ggplot2)
library(dplyr)

grafico <- datos %>%
  ggplot() + 
    geom_point(aes(x = gdpPercap, y = lifeExp, col = continent, size = pop), alpha = 0.8) + theme_minimal() + 
    theme(legend.position = "bottom") + guides(size = "none") + 
    labs(x = "PIB per Capita" ,y = "Esperanza de Vida",  col = "") 

grafico

Ahora para crear la animación simplemente tenemos que pasar una función de transición. Mediante estas funciones, el propio gganimate creara la animación Sí, solo con una función ya se puede crear la animación, veámoslo:

library(gganimate)

grafico +
  transition_time(year)
Animación básica con gganimate

¡Ya tendríamos nuestra animación! Aunque, si te paras a analizar, queda un poco insípida, ¿verdad? Es bastante pequeña, los ejes están fijos, no sabemos en qué año estamos… Y es que, puedes usar una función de transición crear una animación, pero muchos ajustes los deja por defecto haciendo que tu animación no se vea tan bien. No te preocupes, ahora que ya sabemos cómo crear animaciones en R con gganimate, vamos a ver qué ajustes y cambios podemos aplicar para que nuestas animaciones queden fantásticas.

Ajustando nuestras animaciones con R

1. Indicando el número de frame en la transición

Una de las cuestiones clave de una animación es que el usuario sepa por qué se mueve el gráfico, es decir, el usuario tiene que saber qué representa cada momento de la animación.

Para ello, el paquete gganimate incluye una funcionalidad muy interesante: poder incluir esas variables en los labs de ggplot. Cada función de transición tiene sus propias variables para incluirlos en el labs, como podéis ver en la tabla de abajo. En el caso de transition_time la variable es frame_time.

Nombre de la FunciónVariable de labs
transition_components frame_time
transition_events frame_time
transition_filter previous_filter, closest_filter, next_filter
transition_layer previous_layer, closest_layer, next_layer, nlayers
transition_manual previous_frame, current_frame, next_frame
transition_reveal frame_along
transition_states previous_state, closest_state, next_state
transition_time frame_time
grafico +
  transition_time(year) +
  labs(title = "Año: {frame_time}")
Incluir el estado en la animación creada en R con gganimate

Como puedes ver ha incluido la fecha, pero… Se ve pequeño, fuera del gráfico, imposibilita usar el título para otra cosa… A mi es una opción que no me convence del todo.

En mi opinión, una opción más visual e impactante es incluir ese mismo dato dentro del propio gráfico mediante una capa extra de ggplot.De esta forma, podemos usar el título para lo que queramos, podemos dar al estado de la transición la forma que queramos y está dentro del propio gráfico. Veamos un ejemplo:

grafico +
  geom_text(aes(x = min(gdpPercap), y = min(lifeExp), label = as.factor(year)) , hjust=-2, vjust = -0.2, alpha = 0.2,  col = "gray", size = 20) +
  transition_states(as.factor(year), state_length = 0)
Incluir el estado dentro del grafico en animaciones en R con gganimate

Como habrás visto, en este caso he incluido la función transition_states en vez de transition_time y cambiado la variable year a factor. La razón es que las funciones de transición interpolan los datos numéricos, por lo que al mostrarlo en el gráfico aparecerá con decimales. Al convertir el año en factor ese problema desaparece.

Además, he incluido también que el state_length de la transición sea cero. Esta variable permite controlar el tiempo que la animación debe ‘detenerse’ cuando llegas a un nuevo estado. En mi caso, lo pongo a cero porque sino nuestra animación iría a tirones y quedaría feo, pero en otros casos donde se quieren marcar las diferencias, puedes incrementarlo.

Visto este pequeño truco, ¡sigamos mejorando nuestras animaciones!

Mostrar el crecimiendo liberando las escalas de la animación

Si te has fijado, la escala de la animación no se mueve durante la propia animación. Esto genera dos cosas:

  • El crecimiento no parece tan grande. Al tener el valor final visible desde el principio, no tenemos tanta perspectiva de crecimiento.
  • Si la escala es muy amplia y los valores iniciales son bajos (por ejemplo en datos agregados), perdemos la perspectiva de qué pasa al principio, cuando los valores son bajos.

Si queremos evitar esto y para poder ver mejor cómo crecen las variables es mejor ajustar la escala en cada frame y que la escala de los datos vaya cambiando con los mismos. Para ello usaremos la función view_follow.

Un caso muy claro del impacto de las escalas son las gráficas de evolución. Veámos un ejemplo con la evolución del PIB per Cápita de España.

datos %>%
  filter(country == "Spain") %>%
  ggplot(aes(year, pop)) + geom_point() + geom_line() +
  theme_minimal() +
  transition_reveal(year)
Animaciones en R con gganimate. Evolución del PIB sin cambiar escala

Como vemos, al no cambiar los ejes, la animación no parece tan “activa” y no genera tanto impacto. Sin embargo, si incluimos el cambio de ejes automático, la propia velocidad con la que cambian los ejes nos da una imagen mucho mejor de cómo ha ido evolucionando el PIB per Capita.

datos %>%
  filter(country == "Spain") %>%
  ggplot(aes(year, pop)) + geom_point() + geom_line() + 
  geom_text(aes(x = min(year), y = min(pop), label = as.factor(year)) , hjust=-2, vjust = -0.2, alpha = 0.5,  col = "gray", size = 20) +
  theme_minimal() +
  transition_reveal(year) + 
  view_follow()
Animaciones en R con gganimate. Evolucion del PIB cambiando ejes

Como ves estos dos pequeños trucos han mejorado bastante la animación. Pero todavía queda lo mejor y más importante: la renderización de la animación.

Renderización: la clave para crear buenas animaciones con R

Frames y duración: la clave para una buena visualización

Renderizar consiste en convertir nuestros comandos de R en una animación. Es en este paso cuando podemos personalizar muchos de los aspectos clave de la animación, tales como:

  • El ancho y alto de la animación, para crear una animación que se vea bien en el dispositivo donde lo vayamos a compartir.
  • Duración, número de frames y número de frames por segundo (nfps): para conseguir que tu animación se vea fluída.
  • Tipo de archivo de salida: por si no te gustan los gifs y prefieres un vídeo… se puede hacer también.

Para renderizar nuestra animación primero tenemos que guardar el resultado de la animación en un objeto. Así, podremos usar la función animate, en la que podremos renderizar la animación y ajustar todos estos parámetros que hemos comentado.

De cara a crear una animación que visualmente resulte agradable, yo recomiendo ajustar dos parámetros:

  • fps: el ser humano es capaz de ver y distinguir entre 10 y 12 imágenes por segundo. A partir de ese ratio, el cerebro en vez de ver imágenes ve una animación (fuente). Por tanto, el número de frames por segundo siempre debería ser superior a 12. Yo, personalmente, lo suelo fijar en 25fps, ya que da una animación muy fluída y ni la animación pesa tanto ni tarda tanto en exportarse.
  • duration: cuánto quieres que dure la animación dependerá de ti. Claro está que cuantos más estados haya que recorrer, mayor será la duración. En mi opinión, para transiciones largas con muchos estados, lo idea es que cada estado dure 0,5 segundos. En cualquier caso, noexi

Caso práctico: bar chart race

Vamos a ver todo lo que hemos aprendido de cómo crear animaciones en R con gganimate creando una animación muy chula, muy típica y bastante sencilla: la carrera de barras o bar chart race.

Para crear nuestro bar chart race usaremos los países con más PIB per Capita del dataset gapminder. Para ello, lo primero que debemos hacer es obtener el ranking de los países por año respecto al PIB per cápita, algo que podemos hacer fácilmente con dplyr:

datos2 <- datos %>%
  group_by(year) %>%
  arrange(year, desc(gdpPercap)) %>%
  mutate(ranking = row_number()) %>%
  filter(ranking <=15)

head(datos2)
## # A tibble: 6 x 7
## # Groups:   year [1]
##   country       continent  year lifeExp       pop gdpPercap ranking
##   <fct>         <fct>     <int>   <dbl>     <int>     <dbl>   <int>
## 1 Kuwait        Asia       1952    55.6    160000   108382.       1
## 2 Switzerland   Europe     1952    69.6   4815000    14734.       2
## 3 United States Americas   1952    68.4 157553000    13990.       3
## 4 Canada        Americas   1952    68.8  14785584    11367.       4
## 5 New Zealand   Oceania    1952    69.4   1994794    10557.       5
## 6 Norway        Europe     1952    72.7   3327728    10095.       6

Con esto, ya podemos crear fácilmente nuestro la animación bar chart race en R con gganimate. En este caso incluiremos las funciones enter_fade y exit_fade, que harán un efecto de desvanecimiento cuando nuevos países aparecen o desaparecen. Además, usaremos también la función ease_aes para hacer que la animación no sea lineal y así se vea más bonita:

animacion <- datos2 %>%
  ggplot() +
  geom_col(aes(ranking, gdpPercap, fill = country)) +
  geom_text(aes(ranking, gdpPercap, label = gdpPercap), hjust=-0.1) +
  geom_text(aes(ranking, y=0 , label = country), hjust=1.1) + 
  geom_text(aes(x=15, y=max(gdpPercap) , label = as.factor(year)), vjust = 0.2, alpha = 0.5,  col = "gray", size = 20) +
  coord_flip(clip = "off", expand = FALSE) + scale_x_reverse() +
  theme_minimal() + theme(
    panel.grid = element_blank(), 
    legend.position = "none",
    axis.ticks.y = element_blank(),
    axis.title.y = element_blank(),
    axis.text.y = element_blank(),
    plot.margin = margin(1, 4, 1, 3, "cm")
  ) +
  transition_states(year, state_length = 0, transition_length = 2) +
  enter_fade() +
  exit_fade() + 
  ease_aes('quadratic-in-out') 

animate(animacion, width = 700, height = 432, fps = 25, duration = 15, rewind = FALSE)
Animación Bar Chart Race creada en R con gganimate

Conclusión de crear animaciones en R: llevando los gráficos al siguiente nivel

Saber cómo crear animaciones en R es bastante algo bastante sencillo y muy práctico. Si quieres que tus gráficos tengan más impacto y tienes la opción de poder mostrar las gráficas mediante una animación, te motivo a que lo hagas. Pero, no solo te quedes en eso. Las animaciones sirven para muchas más cosas.

En mi caso, por ejemplo, las he utilizado para explicar de forma gráfica y súper sencilla cómo funciona el algoritmo kmeans, pero podrías usarlo también para explicar el funcionamiento de redes neuronales, la mejora en el aprendizaje de modelos de machine learning… ¡Hasta para mostrar jugadas y acciones concretas en análisis deportivos!

Por tanto, te dediques a lo que te dediques, espero que aprender a crear animaciones en R con el paquete gganimate así como los trucos que te he explicado te hayan resultado útiles.

Como siempre, si te gustaría que escribiese sobre un tema en concreto, no dudes en dejar tu sugerencia en la encuesta que sale abajo o en escribirme por Linkedin. ¡Nos vemos en la siguiente!