简体   繁体   中英

gganimate: How to make stacked bar chart grow smoothly upwards from x-axis

I'm having trouble animating a stacked static plot. (See animation below)

The animation moves in a volatile way from left to right, instead of each bar growing upwards from the x-axis. The stacked parts also don't grow very smoothly together, which I can't seem to solve.

What do I need to change in my code, so that, as the animated plot transitions along the x-axis, the individual bars grow upwards? I would also like to have the stacked bars grow more smoothly, so the stacked bar parts aren't "thrown" on top of each other.

How is that possible?

The top gif in this article is what I'm looking for, but I don't understand how and where his code differs from mine: ideal animation

Here is my reprex:

#Static df
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
year <- as.numeric(c(1996:2015,
                       1996:2015,
                       1996:2015))
c <- c(39, 40, 67, 80, 30, 140, 90, 23, 100, 123,
       140, 160, 100, 89, 173, 200, 32, 90, 100, 211,
       1, 2, 1, 13, 3, 3, 30, 1, 3, 3,
       1, 1, 20, 2, 1, 10, 1, 2, 1, 1,
       1, 3, 1, 2, 1, 3, 1, 3, 6, 1,
       1, 30, 1, 1, 8, 9, 1, 32, 1, 1)
cat <- as.character(c("out", "out", "out", "out", "out", "out", "out", "out", "out", "out",
                   "out", "out", "out", "out", "out", "out", "out", "out", "out", "out",
                   "in", "in", "in", "in", "in", "out", "in", "in", "in", "in",
                   "in", "in", "in", "in", "in", "in", "in", "in", "in", "in",
                   "other", "other", "other", "other", "other", "other", "other", "other", "other", "other",
                   "other", "other", "other", "other", "other", "other", "other", "other", "other", "other"))
cat <- as.factor(cat)
static_df_test <- data.frame(year, c, cat) %>%
  select(year, cat, c) %>%
  arrange(year, cat)


#Static plot
library(ggplot2)
(static_plot <- ggplot(static_df_test) +
    geom_bar(data = static_df_test, stat="identity", position ="stack",
             aes(x = year, y = c, fill = cat)) +
    scale_x_continuous(breaks = seq(1996, 2015, 1),
                       expand = c(0.003, 0.003),
                       labels = c(1996, 97, 98, 99, 2000,
                                  "01", "02", "03", "04", "05", "06",
                                  "07", "08", "09", 10, 11, 12, 13, 14, 15)) +
    scale_y_continuous(breaks = seq(0, 250, 25),
                       expand = c(0,0),
                       limits = c(0,250)) +
    labs(x = "year", y = "c")
)

#Animated plot
library(gganimate)
library(ggplot2)
ani <- (static_plot) +
  transition_time(as.integer(year)) +
  enter_grow() + shadow_mark(past = TRUE)

animate(ani, fps = 8, 50, duration = 15,
        width = 1500, height = 750, renderer = gifski_renderer())

Right now, the bars transition by moving rightwards off of the previous bar. See the current animation here: 当前动画

Thank you in advance for any help!

There is likely a more correct way to do this, but it can be accomplished by changing the way you construct your initial static plot and using transition_layers() and enter_drift() .

Note that to simplify my example I am only including years 1996-2000. To animate all years simply copy and paste the geom_bar() sections and change the year being filtered.

#Static plot
library(ggplot2)
(static_plot <- ggplot(static_df_test) +
    geom_bar(data = static_df_test %>% filter(year == 1996), stat="identity", position ="stack",
             aes(x = year, y = c, fill = cat)) +
    geom_bar(data = static_df_test %>% filter(year == 1997), stat="identity", position ="stack",
             aes(x = year, y = c, fill = cat)) +
    geom_bar(data = static_df_test %>% filter(year == 1998), stat="identity", position ="stack",
             aes(x = year, y = c, fill = cat)) +
    geom_bar(data = static_df_test %>% filter(year == 1999), stat="identity", position ="stack",
             aes(x = year, y = c, fill = cat)) +
    geom_bar(data = static_df_test %>% filter(year == 2000), stat="identity", position ="stack",
             aes(x = year, y = c, fill = cat)) +
    scale_x_continuous(breaks = seq(1996, 2015, 1),
                       expand = c(0.003, 0.003),
                       labels = c(1996, 97, 98, 99, 2000,
                                  "01", "02", "03", "04", "05", "06",
                                  "07", "08", "09", 10, 11, 12, 13, 14, 15)) +
    scale_y_continuous(breaks = seq(0, 250, 25),
                       expand = c(0,0),
                       limits = c(0,250)) +
    labs(x = "year", y = "c")
)

#Animated plot
library(gganimate)
library(ggplot2)

ani <- (static_plot) +
  transition_layers(layer_length = 1, transition_length = 2) +
  enter_drift(x_mod = 0, y_mod = -max(static_df_test$c))

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

By placing each year-based bar on its own layer, we can use transition_layers() to make them appear one by one while keeping all old layers. We use enter_drift() to animate each bar as if it is drifting upwards from below the graph.

The animated output is here: link

There is an easier solution. Consider your "Year" variable as a factor instead of numeric. This will make the bars grow smoothly upwards just like you want it.

Basically use the following chunk for your static plot code and it will work:

static_plot <- ggplot(static_df_test) +
    geom_bar(data = static_df_test, stat="identity", position ="stack",
             aes(x = as.factor(year), y = c, fill = cat)) +
    scale_y_continuous(breaks = seq(0, 250, 25),
                       expand = c(0,0),
                       limits = c(0,250)) +
    labs(x = "year", y = "c")

I know I am a bit late, but I hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM