Cómo crear animaciones en R con gganimate
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:
- Cada columna debe ser una variable.
- Todas las filan deben referirse a una observación.
- 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)

¡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ón | Variable 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}")

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)

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)

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

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)

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!