0
votes

I have a situation that doesn't seem to fit any of the previous discussions on the order within stacked bars in ggplot2.

i know that the order of both components within a stacked bar and the legend follows the levels of a factor variable assigned to "fill=". But my dataset has both positive values for some levels and negative values for other levels. The order within the stacked bar for the negative values seem to reverse the order of the levels.

Allow me to illustrate with an example:

d <- data.frame(
               group=c(rep(1,4),rep(2,4),rep(3,4)),
               category=c(rep(c("male_for","male_against","female_for","female_against"),3)),
               n=c(rep(c(2,-2),6))
               )

d$category <- factor(d$category,c("male_for","female_for","male_against","female_against"))

ggplot(d)+ geom_bar(aes(group,n,fill=category),stat="identity")

click here to see the image (not sure why it doesn't embed. sorry

As you can see, the order of the levels in the factor variable "category" is male_for, female_for, male_against, female_against. So is the order in the legend. But, I guess because of the negative values of the against groups, the stacked order in the lower half o the chart is reversed of the levels defined in the factor.

Can anyone figure out a solution where the lower half of the bar chart still follows the order in th legend (ie as defined in the factor)?

Thanks a lot!

1

1 Answers

1
votes

The colors are assigned alphabetically, but your legend is assigned by factor order. Since typically factor order is assigned alphabetically, this problem can be frustrating!

There's more than one way to address it. Here's one way - by the way I used geom_col() because that's really what you were using here... the difference? No stat="identity".

# I picked viridis, because I like their colors - but any would work
library(viridis)
library(tidyverse)

colorPal <- viridis::viridis_pal(end = .8)(4)   # 4 colors; no neon yellow

ggplot(d, aes(group, n, fill = category)) + 
  geom_col() + 
  scale_fill_discrete(type = colorPal,
                      limits = c("male_for",
                                 "female_for",
                                 "male_against",
                                 "female_against"))

enter image description here