简体   繁体   中英

Control fill colour order in graph and legend for ggplot::geom_bar position_stack with positive and negative values

I have a df containing three columns:

-"sample" ~containing the sample names -"group" ~containing the group (first up, second up, remain up, remain down, second down, first down) -"value" ~containing the number in each group.

The samples I have ordered in my desired order in sorder , and applied as factor to order the ticks on the x-axis. In similar fashion I ordered the groups in gorder and applied them as factor to order stacks in the graph.

I am happy with the order of the groups (and their colors) in the legend, and would like the stacks to be ordered the same. I have tried re-ordering the factors, but short of picking the colors by hand I have not managed to get the stacks in the same order as the legend. Do you have any suggestions?

require(dplyr)
require(ggplot2)

gorder<-c("first up", "second up", "remain up", "remain down", "second down", "first down")

sorder<-c("55_NST", "40_NST","25_NST","ad_NST", "RH_NST", "FT_ST",  "55_ST", "25_ST")

set.seed(1)
df<-data.frame(
  "sample" =rep(sorder, each=6),
  "group"=rep(gorder, times=8),
  "value"=c(abs(rnorm(48,mean=3000, sd=500))))
df<-df%>%mutate(value =case_when(group %in% c("remain down", "second down", "first down") ~ value *(-1),
                                 !group %in% c("remain down", "second down", "first down") ~ value))


df$sample<-factor(df$sample, levels = sorder)
df$group<-factor(df$group, levels = gorder)

ggplot(df, aes(fill=group, y=value, x=sample)) + 
    geom_bar(position="stack", stat="identity") +
 theme_bw()+
  scale_x_discrete(breaks=sorder, labels=c("55", "40", "25", "AD", "RH", "FT (ST)", "55 (ST)", "25 (ST)"))+
  scale_y_continuous(breaks = seq(from = -12000,to = 12000, by = 2000))+
  labs(y="number of genes", x="RWC")+
  scale_fill_brewer(type = "div", palette = "RdYlGn",direction = -1)

Example graph, I would like the stacks in the same order as the legend colors

The difficulties seem to be the clash between using factors and the way ggplot handles negative values in position_stack .

From the documentation: "Stacking of positive and negative values are performed separately so that positive values stack upwards from the x-axis and negative values stack downward." It seems stacking trumps factors.

So a bit of manual intervention is needed:

1) re-order gorder to deal with stacking reversal of negative values

2) use scale_fill_manual and a reconstructed version of the colorBrewer palette to get the fill colours in the correct order in the chart. With labels in the required order.

3) override the legend guide so that the colours match with the original label order.

There may well be more efficient ways to achieve this...

library(ggplot2)
library(dplyr)
library(forcats)
library(RColorBrewer)

gorder<-c("first up", "second up", "remain up", "remain down", "second down", "first down")

gorder_col <- c("first up", "second up", "remain up", rev(c("remain down", "second down", "first down")))

sorder<-c("55_NST", "40_NST","25_NST","ad_NST", "RH_NST", "FT_ST",  "55_ST", "25_ST")

set.seed(1)

df<-data.frame(
  "sample" = rep(sorder, each=6),
  "group" = rep(gorder, times=8),
  "value" = c(abs(rnorm(48,mean=3000, sd=500))))

df<-
  df %>%
  mutate(value = case_when(group %in% c("remain down", "second down", "first down") ~ value * (-1),
                           !group %in% c("remain down", "second down", "first down") ~ value),
         sample = factor(sample, levels = sorder),
         group = factor(group, levels = gorder_col))


ggplot(df, aes(fill = group, y = value, x = sample)) + 
  geom_bar(position="stack", stat="identity") +
  theme_bw()+
  scale_x_discrete(breaks = sorder, labels = c("55", "40", "25", "AD", "RH", "FT (ST)", "55 (ST)", "25 (ST)"))+
  scale_y_continuous(breaks = seq(from = -12000,to = 12000, by = 2000))+
  labs(y="number of genes", x="RWC")+
  scale_fill_manual(values = c(brewer.pal(name = "RdYlGn", n = 6)[6:4], brewer.pal(name = "RdYlGn", n = 6)[1:3]),
                    labels = gorder)+
  guides(fill = guide_legend(override.aes = list(fill = brewer.pal(name = "RdYlGn", n = 6)[6:1])))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM