I am trying to make a transition between four stacked bar graphs. The output is not quite what I expected and I haven't been able to figure if it's an error in my code or if it's a bug in gganimate
R package.
This is the data frame I use:
df <- structure(list(name = c("variable", "variable", "variable", "variable",
"variable", "variable", "variable", "variable", "variable", "variable",
"variable", "variable", "variable"), groups = structure(c(3L,
3L, 3L, 3L, 2L, 2L, 2L, 1L, 1L, 1L, 4L, 4L, 4L), .Label = c("group 1",
"group 2", "group 3", "group 4"), class = "factor"), score = structure(c(4L,
3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L), .Label = c("4",
"3", "2", "1"), class = c("ordered", "factor")), percentage = c(8,
38, 38, 16, 17.1428571428571, 40, 42.8571428571429, 40, 20, 40,
5, 65, 30), percentage2 = c("8%", "38%", "38%", "16%", "17.1%",
"40%", "42.9%", "40%", "20%", "40%", "5%", "65%", "30%"), label = c(0.04,
0.27, 0.65, 0.92, 0.0857142857142857, 0.371428571428571, 0.785714285714286,
0.2, 0.5, 0.8, 0.025, 0.375, 0.85)), row.names = c(NA, -13L), class = "data.frame")
When I make a stacked bar graph of just one stage of the groups variable, I get e.g. this:
library(ggplot2)
library(dplyr)
ggplot(filter(df, groups == "group 3"),
aes(x = name, y = percentage, fill = score)) +
geom_bar(stat = "identity", position = "fill", width = 0.8) +
geom_text(aes(y = label, label = percentage2), color = "grey25") +
coord_flip() +
scale_fill_manual(values=c("darkgreen", "lightgreen", "yellow", "red"),
guide = guide_legend(reverse = TRUE), drop=FALSE)
But When I try to add a gganimate
animation of the four different group stages I get this:
library(gganimate)
ggplot(df, aes(x = name, y = percentage, fill = score)) +
geom_bar(stat = "identity", position = "fill", width = 0.8) +
geom_text(aes(y = label, label = percentage2), color = "grey25") +
coord_flip() +
scale_fill_manual(values = c("darkgreen", "lightgreen", "yellow", "red"),
guide= guide_legend(reverse = TRUE), drop = FALSE) +
transition_states(groups, transition_length = 2, state_length = 1)
It seems to add all the percentages (bar lengths) of all the groups to the animation at the same time. I want a transition between the stacked bar graphs of the four different groups without the gaps. How can I get this animation to make a transition between the bars without gaps?
Definitely possible, but in the current version of gganimate
you need to edit your data frame.
g <- ggplot(df, aes(x = name, y = c, fill = score, group = score)) +
geom_col(position = "identity", width = 0.8) +
coord_flip() +
labs(title = "{closest_state}") +
geom_label(aes(y = c, label = percentage2)) +
scale_fill_manual(values = c("darkgreen", "lightgreen", "yellow", "red"),
guide= guide_legend(reverse = TRUE), drop = FALSE) +
transition_states(groups, transition_length = 2, state_length = 1)
animate(g, nframes = 100)
df$c <- ave(df$percentage, df$group, FUN=cumsum)
df <- df[order(df$groups, df$score, df$c), ]
df
name groups score percentage percentage2 label c
10 variable group 1 4 40.00000 40% 0.80000000 100.00000
9 variable group 1 3 20.00000 20% 0.50000000 60.00000
8 variable group 1 2 40.00000 40% 0.20000000 40.00000
7 variable group 2 4 42.85714 42.9% 0.78571429 100.00000
6 variable group 2 3 40.00000 40% 0.37142857 57.14286
5 variable group 2 2 17.14286 17.1% 0.08571429 17.14286
4 variable group 3 4 16.00000 16% 0.92000000 100.00000
3 variable group 3 3 38.00000 38% 0.65000000 84.00000
2 variable group 3 2 38.00000 38% 0.27000000 46.00000
1 variable group 3 1 8.00000 8% 0.04000000 8.00000
13 variable group 4 4 30.00000 30% 0.85000000 100.00000
12 variable group 4 3 65.00000 65% 0.37500000 70.00000
11 variable group 4 2 5.00000 5% 0.02500000 5.00000
========================
Why? In gganimate
version "0.9.9.9999"
the animated plot will not group & stack correctly (a bug, as you pointed out correctly). This is why you need to
c
)c
(so that the bigger ones don't overlap the smaller ones)What was really helpful: to break down the code to the bare bones and just keep the important stuff:
g <- ggplot(df, aes(x = "", y = c, fill = score, group = score)) +
geom_col(position = "identity") +
labs(title = "{closest_state}") +
transition_states(groups, transition_length = 2, state_length = 1)
animate(g, nframes = 10)
This was much easier to work with than the original code. There it became clear that the problem lies somewhere in the interplay of y =
(e.g., c, percentage), group =
(e.g., score, groups), and position =
(e.g., stack, dodge, dodge2, identity, fill).
If you have any questions please do not hesitate to shoot me a message.