ggplot strange ordering of stacked bar

前端 未结 3 896
星月不相逢
星月不相逢 2021-01-24 07:44

I am attempting to create a diverging stacked bar like here, and am experiencing a similar issue to this SO question. My approach is slightly different though as I am managing i

相关标签:
3条回答
  • 2021-01-24 07:50

    You can use position_stack(reverse=TRUE):

    ggplot(x, aes(x = 1, y = count, fill = response)) +
      geom_col(position = position_stack(reverse=TRUE)) +
      scale_fill_brewer(palette = "RdBu") +
      coord_flip()
    
    0 讨论(0)
  • 2021-01-24 07:57

    A tough one! I played with ordering and it seems that geom_bar and geom_col don't like it when you combine positive and negative values in the common same order. So I divided your data inside the dataframe for positive and negative values, generated colors for every response value and used two geoms for positive and negative values separately:

    library(tidyverse)
    library(RColorBrewer)
    x <- tribble(
      ~response, ~count,
      0,         -27,
      1,          -9,
      2,         -41,
      3,         -43,
      4,         -58,
      5,        -120,
      5,         120,
      6,         233,
      7,         379,
      8,         388,
      9,         145,
      10,         61
    ) %>% 
      # Get absolute values and add dummy to distuingish positive and negative values
      mutate(subzero = count < 0,
             count = abs(count))
    
    # Generate variable with colors from ColorBrewer for every response level (ugly but works)
    colors <- brewer.pal(length(unique(x$response)),"RdBu")
    x$colors <- NA
    for (i in 1:nrow(x)){
      x$colors[i] <- colors[x$response[i]+1]
    }
    
    
    ggplot() +
      geom_bar(data = x[x$subzero==T,], aes(x = "", y = -count, fill = reorder(colors, response)), position="stack", stat="identity") +
      geom_bar(data = x[x$subzero==F,], aes(x = "", y = count, fill = reorder(colors, -response)), position="stack", stat="identity") +
      geom_hline(yintercept = 0, color =c("black")) +
      scale_fill_identity("Response", labels = unique(x$response), breaks=unique(x$colors), guide="legend") +
      coord_flip() +
      labs(y="",x="") +
      theme(legend.position = "bottom", legend.direction = "horizontal") +
      scale_y_continuous(breaks=seq(-1400,1400,200), limits=c(-1400,1400))
    

    UPD: made Y-scale balanced so it look more clear

    0 讨论(0)
  • 2021-01-24 08:12

    Although not intuitive (for me), use:

    ggplot(x, aes(x = 1, y = order(count), fill = response)) +
      geom_col() +
      scale_fill_brewer(palette = "RdBu",direction=1) +
      coord_flip()
    

    It takes into account the ordering based on response (rather than order(response))

    0 讨论(0)
提交回复
热议问题