Animar distintos ordenamientos para un gráfico de tarta con gganimate

27 de mayo de 2020

Seguimos jugando con gganimate. Aunque creo que nunca usaré este tipo de animación en un proyecto serio, creo que resulta un ejercicio interesante para comprender las tripas de ggplot2 y de gganimate.

Los datos que vamos a usar y la lógica básica para crear el gráfico que servirá de base (varios subconjuntos o pseudocapas de marcas gráficas apiladas) son los mismos que ya tratamos en un post anterior: “Animar distintos ordenamientos para un gráfico de barras con gganimate”.

Preparar los datos

En el post anterior utilizamos geom_col() para crear el gráfico, pero tras varias pruebas infructuosas, en esta ocasión usaremos geom_rect() para generar cada uno de los “quesitos” o porciones de tarta; bueno, realmente crearemos rectángulos, y coord_polar() se encargará de adecuarlos para el gráfico de tarta.

Para poder usar geom_rect() tenemos que proveer los datos que permitirán posicionar los cuatro vértices del rectángulo:

  • xmin y xmax: la forma de crear gráficos de tarta con ggplot2 es un tanto peculiar: hay que crear un gráfico de barras apiladas (con una única columna), y luego aplicar coord_polar(), por lo que el posicionamiento en el eje x es constante para todos las marcas gráficas. Usaremos los valores 0.5 y 1.5
  • ymin e ymax: tal y como hicimos cuando creamos la animación de un gráfico de barras apiladas, vamos a calcular el valor de ymax como la suma acumulada de los valores (las alturas de cada rectángulo) e ymin será la altura acumulada de un rectángulo menos la altura de ese mismo rectángulo.

Además, vamos a añadir una etiqueta correspondiente a cada rectángulo, para lo que necesitamos calcular la posición en el eje y; las etiquetas estarán posicionadas a media altura de cada rectángulo

datos1 <- mpg %>% 
  group_by(drv, class) %>% 
  mutate(class_drv = paste0(class, " - ", drv)) %>% 
  summarise(count = n(),
            class_drv = unique(class_drv)) %>% 
  ungroup() %>% 
  arrange(class_drv) %>% 
  mutate(orden = row_number(),
         ymax = cumsum(count),
         ymin = ymax - count,
         angulo = ymin + (count/2))

datos2 <- datos1 %>% 
  arrange(count) %>% 
  mutate(orden = row_number(),
         ymax = cumsum(count),
         ymin = ymax - count,
         angulo = ymin + (count/2))

datos3 <- datos1 %>% 
  arrange(drv, count) %>% 
  mutate(orden = row_number(),
         ymax = cumsum(count),
         ymin = ymax - count,
         angulo = ymin + (count/2))

datos <- datos1 %>% 
  bind_rows(datos2, datos3, .id = "estado") %>% 
  mutate(estado = case_when(
    estado == 1 ~ "Alfabético",
    estado == 2 ~ "Total",
    TRUE ~ "drv"
  ))

Gráfico base

Vamos a montar el gráfico base como lo haríamos para crear un gráfico de tarta con ggplot2, con la direfencia de que en lugar de usar geom_bar() o geom_col(), usaremos geom_rect().

Además, añadimos un ángulo de inclinación a geom_label(). El cálculo que debemos realizar variará dependiendo del efecto que queramos conseguir: en este ejemplo, queremos que la línea base de las etiquetas sea tangencial al punto central del arco de cada segmento (y como se puede ver, no lo he conseguido del todo).

(
  tarta <- ggplot(datos, aes(x = 1)) +
    geom_rect(aes(
      xmin = 0.5,
      xmax = 1.5,
      ymin = ymin,
      ymax = ymax,
      fill = drv
    ), color = "black") +
    geom_text(aes(
      label = orden,
      x = 1.6,
      y = angulo,
      angle = -ymax ^ 1.075
    )) +
    coord_polar(theta = "y") +
    theme_void()
)

Animación

La animación es idéntica a la que ya usamos para animar la versión con barras:

anim <- tarta + 
  labs(title = "Orden: {closest_state}") +
  transition_states(estado, transition_length = 1, state_length = 3)

animate(anim, nframes = 100)


Más posts