How to gganimate a stacked bar graph?

☆樱花仙子☆ 提交于 2019-12-10 18:25:57

问题


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?


回答1:


Definitely possible, but in the current version of gganimate you need to edit your data frame.

Code

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)

Data

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

========================

Explanation

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

  1. Feature engineer the position of the bar (variable c)
  2. Order the bars by descending size of 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.



来源:https://stackoverflow.com/questions/52830938/how-to-gganimate-a-stacked-bar-graph

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!