Home > Back-end >  How to keep points in gganimate after each frame is rendered
How to keep points in gganimate after each frame is rendered

Time:03-16

I am working in an animated plot using ggplot2 and gganimate. The plot and the animation work fine but I would like to add a way to show/keep the point after each frame is rendered. The data used is next (dput() added at the end):

df
# A tibble: 30 x 3
# Groups:   year [10]
    year type  Sales
   <int> <chr> <dbl>
 1  2011 A      4123
 2  2011 B       525
 3  2011 C      1153
 4  2012 A      4698
 5  2012 B       533
 6  2012 C      1434
 7  2013 A      5028
 8  2013 B       601
 9  2013 C      1629
10  2014 A      5536
# ... with 20 more rows

Which is a three time series about sales in different years. Now the code for the plot is next:

library(ggplot2)
library(gganimate)
#Plot
G1 <- ggplot(df,aes(x=year,y=Sales,color=type,
                          group=type)) 
  geom_point(size=2) 
  geom_line(size=1) 
  scale_x_continuous(breaks = c(2011:2020)) 
  scale_y_continuous(labels = scales::comma) 
  geom_segment(aes(xend = 2019.75, yend = Sales), linetype = 2, colour = 'grey')   
  geom_text(aes(x = 2019.75, label = sprintf("%5.0f", Sales)), hjust = 0,show.legend = F,fontface='bold',color='black')   
  theme(axis.text.x = element_text(face = 'bold',color='black'),
        axis.text.y = element_text(face = 'bold',color='black'),
        legend.text = element_text(face = 'bold',color='black'),
        axis.title = element_text(face = 'bold',color='black'),
        legend.position = 'bottom',
        legend.title = element_text(face = 'bold',color='black'),
        legend.justification = 'center') 
  transition_reveal(year) 
  view_follow(fixed_x = TRUE,fixed_y = TRUE)

This produces the result:

enter image description here

My question is: What do I need to add to the code in order to show/keep the point after each year is revealed? For example after the line moves from 2011 to 2012, the point on 2011 should appear and keep on the plot. The same would be for 2012 and so on. I mean, after each year is passed, how can I show the point?

Moreover is posible to stop the plot when the final year has been reached and keep all the details?

Many thanks for your time.

The data df is next:

#Data
df <- structure(list(year = c(2011L, 2011L, 2011L, 2012L, 2012L, 2012L, 
2013L, 2013L, 2013L, 2014L, 2014L, 2014L, 2015L, 2015L, 2015L, 
2016L, 2016L, 2016L, 2017L, 2017L, 2017L, 2018L, 2018L, 2018L, 
2019L, 2019L, 2019L, 2020L, 2020L, 2020L), type = c("A", "B", 
"C", "A", "B", "C", "A", "B", "C", "A", "B", "C", "A", "B", "C", 
"A", "B", "C", "A", "B", "C", "A", "B", "C", "A", "B", "C", "A", 
"B", "C"), Sales = c(4123, 525, 1153, 4698, 533, 1434, 5028, 
601, 1629, 5536, 614, 1580, 4989, 589, 1567, 4191, 579, 1521, 
4527, 571, 1504, 5096, 612, 1606, 5331, 595, 1616, 3895, 584, 
976)), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-30L), groups = structure(list(year = 2011:2020, .rows = structure(list(
    1:3, 4:6, 7:9, 10:12, 13:15, 16:18, 19:21, 22:24, 25:27, 
    28:30), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", 
"list"))), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-10L), .drop = TRUE))

CodePudding user response:

I think this is what you're looking for. By default, geoms like geom_point only show the current position, not past positions. You can get around this by giving a unique group to the geom_points.

library(ggplot2)
library(gganimate)
library(tibble)

df <- tribble(
  ~year, ~type, ~Sales,
  2011L,   "A",  4123L,
  2011L,   "B",   525L,
  2011L,   "C",  1153L,
  2012L,   "A",  4698L,
  2012L,   "B",   533L,
  2012L,   "C",  1434L,
  2013L,   "A",  5028L,
  2013L,   "B",   601L,
  2013L,   "C",  1629L,
  2014L,   "A",  5536L,
  2014L,   "B",   614L,
  2014L,   "C",  1580L,
  2015L,   "A",  4989L,
  2015L,   "B",   589L,
  2015L,   "C",  1567L,
  2016L,   "A",  4191L,
  2016L,   "B",   579L,
  2016L,   "C",  1521L,
  2017L,   "A",  4527L,
  2017L,   "B",   571L,
  2017L,   "C",  1504L,
  2018L,   "A",  5096L,
  2018L,   "B",   612L,
  2018L,   "C",  1606L,
  2019L,   "A",  5331L,
  2019L,   "B",   595L,
  2019L,   "C",  1616L,
  2020L,   "A",  3895L,
  2020L,   "B",   584L,
  2020L,   "C",   976L
  )

                                                                                                                                                                                                                                                                                           
G1 <- ggplot(df,aes(x=year,y=Sales,color=type,
                    group=type)) 
  geom_point(size=2, 
             # Create a distinct grouping variable for geom_point 
             aes(group = seq_along(year))) 
  geom_line(size=1) 
  scale_x_continuous(breaks = c(2011:2020)) 
  scale_y_continuous(labels = scales::comma) 
  geom_segment(aes(xend = 2019.75, yend = Sales), linetype = 2, colour = 'grey')   
  geom_text(aes(x = 2019.75, label = sprintf("%5.0f", Sales)), hjust = 0,show.legend = F,fontface='bold',color='black')   
  theme(axis.text.x = element_text(face = 'bold',color='black'),
        axis.text.y = element_text(face = 'bold',color='black'),
        legend.text = element_text(face = 'bold',color='black'),
        axis.title = element_text(face = 'bold',color='black'),
        legend.position = 'bottom',
        legend.title = element_text(face = 'bold',color='black'),
        legend.justification = 'center') 
  transition_reveal(year) 
  view_follow(fixed_x = TRUE,fixed_y = TRUE)

# Animate without rewinding
animate(G1, rewind = FALSE)

Created on 2022-03-15 by the reprex package (v2.0.1)

  • Related