thomasp85/gganimate

transition_states computes a wrong nframes

lgaborini opened this issue · 3 comments

Similar issue to #384.
I'm plotting a super simple plot that cycles over discrete states, forcing no transitions.

There are 3 discrete states, so I would expect 3 frames.
I also force 3 frames in the output.

Instead, the output has 4 frames (an extra transitioning frame is added) and one of the states is missing.

Tested with 1.0.8 (CRAN) and the latest 1.0.8.9000.

library(dplyr)
library(ggplot2)
library(gganimate)

p <- mtcars |> 
   ggplot(aes(wt, mpg)) +
   geom_point(
      aes(
         col = gear
      ),
      size = 2
   ) +
   transition_states(
      gear,
      transition_length = 0,
      state_length = 1
   ) +
   labs(
      title = "Frame {frame}/{nframes}"
   )

n_states <- length(unique(mtcars$gear))
n_states
#> [1] 3

a <- animate(
   plot = p,
   nframes = n_states,
   fps = 1,
   detail = 1,
   start_pause = 0,
   end_pause = 0,
   rewind = FALSE
)

a

frame_vars()
#>   frame nframes progress transitioning previous_state closest_state next_state
#> 1     1       4     0.25         FALSE              3             3          3
#> 2     2       4     0.50         FALSE              3             3          3
#> 4     4       4     1.00          TRUE              4             4          5
#>                                                                              frame_source
#> 1 C:\\Users\\LORENZ~1\\AppData\\Local\\Temp\\RtmpiiFiZG\\1ca411191ef0/gganim_plot0001.png
#> 2 C:\\Users\\LORENZ~1\\AppData\\Local\\Temp\\RtmpiiFiZG\\1ca411191ef0/gganim_plot0002.png
#> 4 C:\\Users\\LORENZ~1\\AppData\\Local\\Temp\\RtmpiiFiZG\\1ca411191ef0/gganim_plot0003.png

Created on 2023-04-18 with reprex v2.0.2

Thanks!

Bug found, transition_states adds an extra frame if the animation wraps.
Solution: disable wrapping

  transition_states(
      gear,
      transition_length = 0,
      state_length = 1,
      wrap = FALSE
   )

Perhaps disable adding extra frames if transitions are not explicitly desired?

Ok still not correct, not all states are cycled and transitions are still happening (sorry for the spam):

library(ggplot2)
library(gganimate)

p <- mtcars |> 
   ggplot(aes(wt, mpg)) +
   geom_point(
      aes(
         color = gear
      ),
      size = 2
   ) +
   transition_states(
      gear,
      transition_length = 0,
      state_length = 1,
      wrap = FALSE
   ) +
   labs(
      title = "Frame {frame}/{nframes}: Closest gear: {closest_state}"
   )

n_states <- length(unique(mtcars$gear))
n_states
#> [1] 3

a <- animate(
   plot = p,
   nframes = n_states,
   fps = 1,
   detail = 1,
   start_pause = 0,
   end_pause = 0,
   rewind = FALSE
)

a

frame_vars()
#>   frame nframes  progress transitioning previous_state closest_state next_state
#> 1     1       3 0.3333333         FALSE              3             3          3
#> 2     2       3 0.6666667          TRUE              3             3          4
#> 3     3       3 1.0000000          TRUE              4             4          5
#>                                                                              frame_source
#> 1 C:\\Users\\LORENZ~1\\AppData\\Local\\Temp\\RtmpikQ5gg\\4d742ed529ab/gganim_plot0001.png
#> 2 C:\\Users\\LORENZ~1\\AppData\\Local\\Temp\\RtmpikQ5gg\\4d742ed529ab/gganim_plot0002.png
#> 3 C:\\Users\\LORENZ~1\\AppData\\Local\\Temp\\RtmpikQ5gg\\4d742ed529ab/gganim_plot0003.png

Created on 2023-04-19 with reprex v2.0.2

I'll look into this but I also think it is somewhat of a case of using the wrong transition, since transition_states() is explicitly for adding interpolation between states. I believe using transition_manual() you should be able to get your desired output directly?