I created an animated bar chart which displays the scored goals by some players. Below the whole code is displayed how I came to the output.
The animation works as wished. However, bars with the same value overlap.
I would like to prevent the bars from overlapping. The best case would be for the player who scored first to be displayed above other players at the same rank.
The order of players who scored equally at the beginning of the animation does not matter.
library(tidyverse)
library(gganimate)
theme_set(theme_classic())
df <- data.frame(Player = rep(c("Aguero", "Salah", "Aubameyang", "Kane"), 6),
Team = rep(c("ManCity", "Liverpool", "Arsenal", "Tottenham"), 6),
Gameday = c(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6),
Goals = c(0,1,2,0,1,1,3,1,2,1,3,2,2,2,4,3,3,2,4,5,5,3,5,6),
stringsAsFactors = F)
gap <- df %>%
group_by(Gameday) %>%
mutate(rank = min_rank(-Goals) * 1,
Value_rel = Goals/Goals[rank==1],
Value_lbl = paste0(" ", Goals)) %>%
filter(rank <=10) %>%
ungroup()
p <- ggplot(gap, aes(rank, group = Player, stat = "identity",
fill = as.factor(Player), color = as.factor(Player))) +
geom_tile(aes(y = Goals/2,
height = Goals,
width = 0.9), alpha = 0.8, color = NA) +
geom_text(aes(y = 0, label = paste(Player, " ")), vjust = 0.2, hjust = 1) +
geom_text(aes(y=Goals,label = Value_lbl, hjust=0)) +
coord_flip(clip = "off", expand = FALSE) +
scale_y_continuous(labels = scales::comma) +
scale_x_reverse() +
guides(color = FALSE, fill = FALSE) +
labs(title = "Gameday {closest_state}", x="", y = "Goals scored") +
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(Gameday, transition_length = 4, state_length = 1) +
ease_aes('cubic-in-out')
p
The code outputs following plot:
Additional note:
At the end, the bars should be displayed according to the example below. Preferably the bars should not be on the same height, to increase the readability.
Thank you very much for your effort!
Edited solution based on clarification:
Original solution:
Note: This isn't perfect. I imagine the simple logic above for determining player order within the same day / rank won't be ideal if there are too many players / too many days, since it only looks backwards by one day. But it works for this example, & I don't know enough about football (at least I think this is football?) to extrapolate about your use case.