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 wishe
Edited solution based on clarification:
gap %>%
# for each player, note his the rank from his previous day
group_by(Player) %>%
arrange(Gameday) %>%
mutate(prev.rank = lag(rank)) %>%
ungroup() %>%
# for every game day,
# sort players by rank & break ties by previous day's rank
group_by(Gameday) %>%
arrange(rank, prev.rank) %>%
mutate(x = seq(1, n())) %>%
ungroup() %>%
ggplot(aes(x = x, y = Goals, fill = Player, color = Player)) +
# geom_tile(aes(y = Goals/2, height = Goals, width = width)) +
geom_col() +
geom_text(aes(y = 0, label = Player), hjust = 1) +
geom_text(aes(label = Value_lbl), hjust = 0) +
# rest of the code below is unchanged from the question
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(),
axis.text.y = element_blank(),
plot.margin = margin(1,1,1,4, "cm")) +
transition_states(Gameday, transition_length = 4, state_length = 1) +
ease_aes('cubic-in-out')
Original solution:
gap %>%
# for each player, note his the rank from his previous day
group_by(Player) %>%
arrange(Gameday) %>%
mutate(prev.rank = lag(rank)) %>%
ungroup() %>%
# for every game day & every rank,
# reduce tile width if there are multiple players sharing that rank,
# sort players in order of who reached that rank first,
# & calculate the appropriate tile midpoint depending on how many players are there
group_by(Gameday, rank) %>%
mutate(n = n_distinct(Player)) %>%
mutate(width = 0.9 / n_distinct(Player)) %>%
arrange(prev.rank) %>%
mutate(x = rank + 0.9 * (seq(1, 2 * n() - 1, by = 2) / 2 / n() - 0.5)) %>%
ungroup() %>%
ggplot(aes(x = x, fill = Player, color = Player)) +
geom_tile(aes(y = Goals/2, height = Goals, width = width)) +
geom_text(aes(y = 0, label = Player), hjust = 1) +
geom_text(aes(y = Goals, label = Value_lbl), hjust = 0) +
# rest of the code below is unchanged from the question
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(),
axis.text.y = element_blank(),
plot.margin = margin(1,1,1,4, "cm")) +
transition_states(Gameday, transition_length = 4, state_length = 1) +
ease_aes('cubic-in-out')
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.