2

How do I combine geom_smooth(method = "lm) function with gganimate()'s transition_layers, so that, as the individual bars drift/grow upwards, the linear line of geom_smooth appears, like so: Example of desired appearance of geom_smooth line The only difference is that in my case, instead of the points, the bars would drift upwards as the line appears.

The bars current work well, appearing by drifting upwards, made possible by using the transition_layers function of gganimate.

However, I can't figure out how to add the geom_smooth line, so it appears as the bars grow upwards. Right now, the line appears just at the end, as seen below.

See below for the current look of the animation.

Here is a simple reprex of my problem:

#Df for reprex
library(ggplot2)
library(tidyverse)

year <- as.numeric(c(1996:2002,
                     1996:2002,
                     1996:2002))
c <- c(39, 40, 67, 80, 30, 140, 90, 23, 100, 123,
       140, 1, 2, 1, 13, 3, 3, 30, 1, 3, 3)
df <- data.frame(year, c) %>%
  select(year, c) %>%
  arrange(year)

#Static plot
(static_plot <- ggplot(data = df) +
    geom_bar(data = df %>% filter(year == 1996), stat="identity", position ="stack",
             aes(x = year, y = c)) +
    geom_bar(data = df %>% filter(year == 1997), stat="identity", position ="stack",
             aes(x = year, y = c)) +
    geom_bar(data = df %>% filter(year == 1998), stat="identity", position ="stack",
             aes(x = year, y = c)) +
    geom_bar(data = df %>% filter(year == 1999), stat="identity", position ="stack",
             aes(x = year, y = c)) +
    geom_bar(data = df %>% filter(year == 2000), stat="identity", position ="stack",
             aes(x = year, y = c)) +
    geom_bar(data = df %>% filter(year == 2001), stat="identity", position ="stack",
             aes(x = year, y = c)) +
    geom_bar(data = df %>% filter(year == 2002), stat="identity", position ="stack",
             aes(x = year, y = c)) +
  labs(y = "year",
       x = "c",
       title = "Reprex") +
  geom_smooth(df, mapping = aes(x = year, y = c), method = "lm",
              colour = "black", se = F)
  )

#Animation
library(gganimate)
anim <- static_plot +
  transition_layers(layer_length = 1, transition_length = 1) +
  enter_drift(x_mod = 0, y_mod = -max(df$c))

animate(anim, fps = 10, duration = 10,
        width = 600, height = 500, renderer = gifski_renderer())

Current animation

Will M
  • 692
  • 9
  • 20
  • A relevant answer has been found. However, that does not make the regression line appear smoothly. I would still really appreciate an answer that incorporates the regression line to appear in one smooth transition, like the example in the question above. This solution makes the line appear in several distinct chunks: https://community.rstudio.com/t/gganimate-how-to-combine-geom-smooth-method-lm-with-transition-layers/40939/2?u=willrm – Will M Sep 27 '19 at 22:14
  • on the first view i would say, given the current solutions, the "smoothness" scales with the amount of bars you can add to your plot. Note, that in the linked "smooth" graph (as well as in your graph) the line is updated for each new value on the x-axis / abscissa,...Do you have monthly data available / could you split it in more "bars"? – Tonio Liebrand Sep 28 '19 at 10:39
  • 1
    I believe my solution accomplishes your goal of making the regression line appear smoothly and transition smoothly and shift based on the available data at each point. Please let me know if that wasn't what you had in mind. – Jon Spring Oct 05 '19 at 02:41
  • Cheers! I just verified your answer. Would you know how to change your animation so the regression line doesn’t change every step and is rather based on the full dataset? – Will M Oct 05 '19 at 17:19
  • 1
    Do you want the regression line to start out in its final position and stay there while the data fills in? – Jon Spring Oct 06 '19 at 02:57
  • Not exactly, the ideal scenario would be to have the final form of the regression line slowly appears along the bars. So, the regression line should appear like yours. However, instead of it being based on the data up until each point in time, it would, from the very beginning, be based on all data. As the bars grow, the full regression line would then slowly appear, however not changing "form". The difficulty for me lies in having it appear smoothly, not in chunks. – Will M Oct 06 '19 at 20:33
  • @JonSpring would you be able to help with my other related question? https://stackoverflow.com/questions/60856938/animate-points-and-regression-line-along-date-with-gganimate – Will M Mar 25 '20 at 21:51

2 Answers2

9

Here's an approach where the data is replicated and then filtered so each version shows progressively more years.

library(dplyr); library(tidyr)

animate(
  df %>%
    count(year, wt = c, name = "c") %>%   # Aggregate for each year's total
    uncount(7, .id = "year_disp") %>%     # Make 7 copies, one for each year
    arrange(year_disp, year) %>% 
    mutate(year_disp = year_disp + min(df$year) - 1) %>%
    filter(year <= year_disp) %>%         # Only keep years up to "year_disp"
    ggplot(aes(year, c)) +
    geom_col(aes(group = year)) +   # "group" here connects each year to itself between frames
    geom_smooth(method = "lm", se = F) +
    transition_states(year_disp) +
    enter_drift(y_mod = -max(df$c)),
  fps = 10, duration = 10,
  width = 600, height = 500, renderer = gifski_renderer())

enter image description here

Jon Spring
  • 55,165
  • 4
  • 35
  • 53
  • would you be able to help with my other related question? https://stackoverflow.com/questions/60856938/animate-points-and-regression-line-along-date-with-gganimate – Will M Mar 25 '20 at 21:52
1

The geom-line is calculated in the end and hence it appears only at the end. After each calculation of geom-bar, you have to calculate the geom-line as well, so that the line appears simultaneously with the Bars growing.

geom_bar(data = df %>% filter(year == 1997), stat="identity", position ="stack",
             aes(x = year, y = c)) +
geom_line(filter(df, year %in% c(1996, 1997)), mapping = aes(x = year, y = lm),
                colour = "black")

Do this for all the years and you should be getting the expected result!

Sreeram Nair
  • 2,369
  • 12
  • 27
  • would you be able to help me with this other related question? https://stackoverflow.com/questions/60856938/animate-points-and-regression-line-along-date-with-gganimate – Will M Mar 25 '20 at 21:52