How to plot a Stacked and grouped bar chart in ggplot?

前端 未结 2 870
别那么骄傲
别那么骄傲 2020-11-30 10:58

I have a data frame like below:

id    month     type    count
___  _______   ______   ______
1      1          1       10
1      1          2       09
1              


        
相关标签:
2条回答
  • 2020-11-30 11:02

    This problem can be solved much more cleanly with facet_grid:

    library(tidyverse)
    read_tsv("tmp.tsv", col_types = "ccci") %>%  
    ggplot(aes(x=month, y=count, fill=type)) + geom_col() + facet_grid(.~id)
    

    Note that you have to specify the first three columns as "character" in the col_types argument otherwise it won't look so good. It would be even better to replace the numeric codes with something meaningful (e.g. make the months into ordered factors "January", "February" instead of 1, 2; something similar for type and id).

    0 讨论(0)
  • 2020-11-30 11:18

    Suppose you want to plot id as x-axis, side by side for the month, and stack different types, you can split data frame by month, and add a bar layer for each month, shift the x by an amount for the second month bars so they can be separated:

    barwidth = 0.35
    
    month_one <- filter(df, month == 1) %>% 
        group_by(id) %>% arrange(-type) %>% 
        mutate(pos = cumsum(count) - count / 2)   # calculate the position of the label
    
    month_two <- filter(df, month == 2) %>% 
        group_by(id) %>% arrange(-type) %>% 
        mutate(pos = cumsum(count) - count / 2)
    
    ggplot() + 
        geom_bar(data = month_one, 
                 mapping = aes(x = id, y = count, fill = as.factor(type)), 
                 stat="identity", 
                 position='stack', 
                 width = barwidth) + 
        geom_text(data = month_one, 
                  aes(x = id, y = pos, label = count )) + 
        geom_bar(data = filter(df, month==2), 
                 mapping = aes(x = id + barwidth + 0.01, y = count, fill = as.factor(type)), 
                 stat="identity", 
                 position='stack' , 
                 width = barwidth) + 
        geom_text(data = month_two, 
                  aes(x = id + barwidth + 0.01, y = pos, label = count )) + 
        labs(fill  = "type")
    

    gives:


    dput(df)
    structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 
    2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L), month = c(1L, 1L, 1L, 2L, 2L, 
    2L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 2L, 2L), type = c(1L, 
    2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 
    3L), count = c(10L, 9L, 26L, 60L, 90L, 80L, 10L, 9L, 26L, 60L, 
    90L, 80L, 10L, 9L, 26L, 60L, 90L, 80L)), .Names = c("id", "month", 
    "type", "count"), class = "data.frame", row.names = c(NA, -18L
    ))
    
    0 讨论(0)
提交回复
热议问题