Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get rid of axis flickering caused by coord_flip when using gganimate and view_follow and geom_tile?

Let's say we have this bar chart race with a scaling x-axis. Taking the code exactly from this answer by @Jon Spring and adding the very final line (before the animate line):

library(tidyverse)
library(gganimate)
library(gapminder)
theme_set(theme_classic())

gap <- gapminder %>%
    filter(continent == "Asia") %>%
    group_by(year) %>%
    # The * 1 makes it possible to have non-integer ranks while sliding
    mutate(rank = min_rank(-gdpPercap) * 1) %>%
    ungroup()

p <- ggplot(gap, aes(rank, group = country, 
                     fill = as.factor(country), color = as.factor(country))) +
    geom_tile(aes(y = gdpPercap/2,
                  height = gdpPercap,
                  width = 0.9), alpha = 0.8, color = NA) +

    # text in x-axis (requires clip = "off" in coord_*)
    # paste(country, " ")  is a hack to make pretty spacing, since hjust > 1 
    #   leads to weird artifacts in text spacing.
    geom_text(aes(y = 0, label = paste(country, " ")), vjust = 0.2, hjust = 1) +

    coord_flip(clip = "off", expand = FALSE) +
    scale_y_continuous(labels = scales::comma) +
    scale_x_reverse() +
    guides(color = FALSE, fill = FALSE) +

    labs(title='{closest_state}', x = "", y = "GFP per capita") +
    theme(plot.title = element_text(hjust = 0, size = 22),
          axis.ticks.y = element_blank(),  # These relate to the axes post-flip
          axis.text.y  = element_blank(),  # These relate to the axes post-flip
          plot.margin = margin(1,1,1,4, "cm")) +

    transition_states(year, transition_length = 4, state_length = 1) +
    ease_aes('cubic-in-out') +
    view_follow()

animate(p, fps = 25, duration = 20, width = 800, height = 600)

The issue is that there is flickering in the axis.

How can I fix this? Note that it appears that this derives from the coord_flip code.

See also here for a solution when the code used geom_bar.

However, in my case, the code is using geom_tile. What can I do?

like image 413
bill999 Avatar asked Apr 11 '20 01:04

bill999


1 Answers

I think I found the answer, after being inspired by this posted issue on github. As you pointed out in your question, it's apparently a known issue that you get axis flickering when using coord_flip() with animations.

I tried geom_rect in place of geom_tile, but that still gets you flickering.

What does work is geom_colh in place of geom_tile! This is from the ggstance package. Here's the code:

ggplot(gap, aes(y=rank, group = country, 
    fill = as.factor(country), color = as.factor(country))) +

geom_colh(aes(x=gdpPercap/2), width=0.9, alpha = 0.8, color = NA) +

geom_text(aes(x = 0, label = paste(country, " ")), vjust = 0.2, hjust = 1) +

scale_y_reverse(labels = scales::comma) +
guides(color = FALSE, fill = FALSE) +
coord_cartesian(clip='off') +

labs(title='{closest_state}', x = "GFP per capita", y = "") +
theme(
    plot.title = element_text(hjust = 0, size = 22),
    axis.ticks.y = element_blank(),
    axis.text.y  = element_blank(),
    plot.margin = margin(1,1,1,4, "cm"),
    axis.line.y = element_blank()) +

transition_states(year, transition_length = 4, state_length = 1) +
ease_aes('cubic-in-out') +
view_follow()

So to go over what was changed:

  • geom_colh used in place of geom_tile. You need the ggstance package for this - I didn't even try geom_col, but I imagine you're going to get flickering with that.

  • scale_y_reverse this call contains your labels call in place of scale_y_continuous, since you want to reverse the axis too. Probably would be best if you set your y aesthetic as country and then reordered for rank.... but eh, this works as you have it.

  • coord_cartesian(clip='off') This serves the same purpose as the settings on your coord_flip. If you want to overplot the country names, you need this in order to get that text to go "outside" the plot area. Again - would be better if you used y=country, but again... eh, it works.

  • axis.line.y = element_blank() removed for easy viewing - or you can keep it and play with your plot area margins between the axis and the start of the columns. Again - eh, it works.

enter image description here

There may be other ways, but this seems to be a reasonable workaround. Nice graphic!

like image 80
chemdork123 Avatar answered Oct 22 '22 14:10

chemdork123