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?
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.
There may be other ways, but this seems to be a reasonable workaround. Nice graphic!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With