0

With a basketball dataset, I'm trying to build an animation of a line graph with a metric called EPV on y-axis and time on x-axis. I can get this to work, but now I'd like to add text labels at specific time points where any event occurs. An event is when an action happens in a basketball game, like a possession, dribble, or pass. Here is what I have so far:

enter image description here

library(tidyverse)
library(gganimate)
library(ggrepel)
theme_set(theme_minimal())

epv_curve_228 <- read_csv("https://raw.githubusercontent.com/jasonbaik94/stackoverflow-data/master/epv_curve_228.csv")

epv_curve_228 %>%
  ggplot() +
  geom_path(aes(x = 720 - game_clock, y = epv.smooth)) +
  # Add description of event for home players
  geom_label_repel(aes(x = 720 - game_clock, y = epv.smooth, label = h1_event), force = 5) +
  geom_label_repel(aes(x = 720 - game_clock, y = epv.smooth, label = h2_event), force = 5) +
  geom_label_repel(aes(x = 720 - game_clock, y = epv.smooth, label = h3_event), force = 5) +
  geom_label_repel(aes(x = 720 - game_clock, y = epv.smooth, label = h4_event), force = 5) +
  geom_label_repel(aes(x = 720 - game_clock, y = epv.smooth, label = h5_event), force = 5) +
  # Add description of event for away players
  geom_label_repel(aes(x = 720 - game_clock, y = epv.smooth, label = a1_event), force = 5) +
  geom_label_repel(aes(x = 720 - game_clock, y = epv.smooth, label = a2_event), force = 5) +
  geom_label_repel(aes(x = 720 - game_clock, y = epv.smooth, label = a3_event), force = 5) +
  geom_label_repel(aes(x = 720 - game_clock, y = epv.smooth, label = a4_event), force = 5) +
  geom_label_repel(aes(x = 720 - game_clock, y = epv.smooth, label = a5_event), force = 5) +
  transition_reveal(720 - game_clock) +
  labs(x = "Time (Seconds)",
       y = "EPV",
       title = "Possession #228 EPV") 

The problem is that NOT ALL OF the text labels (Events such as Dribble, Possession, etc) appear. I know that the NA labels can be eliminated by replacing the NA with "". I'm not sure how I can show all the text labels associated with all the events. I see at least 4 different event values

  • I can't reproduce your problem, but reason for it might be that you're using `geom_label_repel` in a wrong way. You have to pass all labels in a single call so they would be repelled. Now each `geom_label_repel` call has only single entry. – pogibas Apr 13 '19 at 15:33
  • Oops sorry, I forgot to include my packages. I've done that –  Apr 13 '19 at 16:31
  • @PoGibas I've used `gather` on my dataset and passed all my labels in a single call using `geom_label_repel(aes(x = 720 - game_clock, y = epv.smooth, label = event)) ` but this still gives me same problem –  Apr 13 '19 at 16:43

1 Answers1

1

Here's an approach. I found it useful to consolidate the events, and then fill some following rows (in this case 5, to align with 100 frames and ~500 rows) to avoid missing events which might happen to occur in between frames of the animation.

epv_curve_228_excerpt <- epv_curve_228 %>%
  select(game_clock, epv.smooth, ends_with("event")) %>%
  unite(event, a1_event:h5_event) %>%
  mutate(event = str_remove_all(event, "NA|_")) %>%
  # Add event to a few following time stamps so we don't miss any in our frames
  mutate(event_count = cumsum(event != "")) %>%
  group_by(event_count) %>%
  mutate(event_fill = if_else(row_number() <= 5, first(event), "")) %>%
  ungroup()


 a <- ggplot(epv_curve_228_excerpt,
         aes(x = 720 - game_clock, 
             y = epv.smooth,
             label = event_fill)) +
  geom_path() +
    geom_label_repel(nudge_x = -1, size = 5) +
    transition_reveal(720 - game_clock) +
    shadow_wake(wake_length = 0.5, alpha = 0.7, size = 3,
                exclude_layer = 1)

 animate(a, nframes = 100, width = 600, height = 250)

enter image description here

Jon Spring
  • 55,165
  • 4
  • 35
  • 53
  • Excellent. Use `shadow_wake(..., wrap = F)` to avoid showing the last labels at the beginning. – Martin Aug 27 '22 at 07:00