rggplot2gganimateggrepel

Getting transition_states, geom_label_repel and enter_fade to work together


I'm drawing a scatterplot where I'd like to highlight different observations as time passes. Sometimes, these observations are close together, so I'm using geom_label_repel to do so. I'd also like to use enter_fade and exit_fade in order to make smoother the transition between phases of the animation.

I see from elsewhere (eg here) that the position of the geom_label_repel can be made consistent with the use of a seed. However, this isn't working for me with enter_fade and exit_fade: the geom_label_repel jumps around as the labels enter and exit.

Is there a way that the geom_label_repel can stay where it is through these phases?

Here's an example of how I've attempted to implement this, which hopefully will illustrate the problem I'm running into.

enter image description here


set.seed(24601)
library(stringi)
library(tidyverse)
library(gganimate)
library(ggrepel)

x <- 
  rnorm(100, 0, 1)
y <- 
  rnorm(100, 0, 1)
names <- 
  stri_rand_strings(100,
                    5)
categories <- 
  rep(c("a", "b", "c", "d", "e"), 5)

ggplot(data.frame(x, y, names, categories)) + 
  aes(x = x,
      y = y) + 
  geom_point(data = . %>% 
               select(- categories)) + 
  geom_label_repel(aes(label = names,
                       group = categories),
                   seed = 24601) + 
  transition_states(categories)  + 
  enter_fade() + 
  exit_fade()

Solution

  • What's happening is that during the transitions, the location and number of labels within the plot are not consistent. This causes geom_label_repel() to force labels away from each other. You can set force = 0 so that your labels are not repelled from each other (default force is 1), but instead only repelled from points.

    ggplot(data.frame(x, y, names, categories)) + 
      aes(x = x,
          y = y) + 
      geom_point(data = . %>% 
                   select(- categories)) + 
      geom_label_repel(aes(label = names,
                           group = categories),
                       seed = 24601,
                       force = 0) + 
      transition_states(categories)  + 
      enter_fade() + 
      exit_fade()
    

    As you can see, you will have some labels overlap. However, if important, you could play with lower values of force (e.g. force = 0.1) so the labels only shift slightly but overlap less.

    Although most are stable, I am getting a couple of random labels popping up and not transitioning, will investigate.