Home > OS >  Stacked Bar Graph using ggplot with Negative Values in R
Stacked Bar Graph using ggplot with Negative Values in R

Time:11-19

Here is my dataset-

df<- data.frame(Comparison=c("Control vs SA","Control vs SA","Control vs SA","Control vs SA","Control vs SA","Control vs SA","Control vs SA","Control vs SA","Control vs SA","Control vs SA",
                                         "SA3MA vs SA","SA3MA vs SA","SA3MA vs SA","SA3MA vs SA","SA3MA vs SA","SA3MA vs SA","SA3MA vs SA","SA3MA vs SA","SA3MA vs SA","SA3MA vs SA",
                                         "Control vs HS","Control vs HS","Control vs HS","Control vs HS","Control vs HS","Control vs HS","Control vs HS","Control vs HS","Control vs HS","Control vs HS",
                                         "HSLC vs HS","HSLC vs HS","HSLC vs HS","HSLC vs HS","HSLC vs HS","HSLC vs HS","HSLC vs HS","HSLC vs HS","HSLC vs HS","HSLC vs HS"),
                LFC_Band=c(-4,-2,-1,-0.5,-0.25,0.25,0.5,1,2,4,
                           -4,-2,-1,-0.5,-0.25,0.25,0.5,1,2,4,
                           -4,-2,-1,-0.5,-0.25,0.25,0.5,1,2,4,
                           -4,-2,-1,-0.5,-0.25,0.25,0.5,1,2,4),
                Number_of_Genes=c(-36,-540,-2198,-3025,-6002,6517,3462,2466, 500,1,-620,-2317,-3318,-2748,-2264,2706,2046,3079,3013,2073,-119,-606,
                                  -1640,-2886,-7451,6944,3147,1592, 267,0,26,0,0, -44,-901 -11699,10969, 754,0,12,0))

What I am trying to do is create a stacked bar plot using ggplot.

chart_x <- ggplot(data = df, aes(y=(Number_of_Genes), 
                                            x=Comparison, group = Comparison)) 
  geom_col(aes(fill=(as.factor(LFC_Band)))) 
  scale_fill_brewer(palette = "Spectral")
chart_x

The resultant is-

stacked graph

But if you see the bottom half is basically flipped. The top half is correct which is 4 till 0.25, while the bottom half starts from -4. Is there a way to flip the bottom half so that it starts from -0.25? In short, what I want is- Needed!

I used MS paint to create that just to show what I am looking for.

I tried other methods where I split the data into two but, it didnt work as well. Any help is much appreciated. :)

CodePudding user response:

Are you looking for such a solution?

library(tidyverse)

df1 <- df %>% 
  filter(Number_of_Genes>=0)
df2 <- df %>% 
  filter(Number_of_Genes<0)

ggplot()   
  geom_bar(data = df2, aes(x=Comparison, y=Number_of_Genes, group = Comparison, fill=factor(LFC_Band)),stat = "identity")  
  geom_bar(data = df1, aes(x=Comparison, y=Number_of_Genes, group = Comparison, fill=factor(LFC_Band)),stat = "identity")  
  scale_fill_brewer(palette = "Spectral")

enter image description here

CodePudding user response:

One option to achieve your desired result would be to:

  1. Convert LFC_Band to a factor before passing your data to ggplot (otherwise we lose the order of the categories in the legend)
  2. Drop group=Comparison so that the stack gets grouped by fill= LFC_Band
  3. Use two geom_col, one for positive, one for negative values.
  4. Reverse the order of the stack for the positive values
  5. Add drop=FALSE to scale_fill_brewer otherwise we lose the order of the categories in the legend)

Additionally I reversed the fill legend but you could drop that if your like

library(ggplot2)

df$LFC_Band <- factor(df$LFC_Band)

ggplot(data = df, aes(x = Comparison, y = Number_of_Genes, fill = LFC_Band))  
  geom_col(data = df[df$Number_of_Genes > 0, ], position = position_stack(reverse = TRUE))  
  geom_col(data = df[df$Number_of_Genes < 0, ])  
  scale_fill_brewer(palette = "Spectral", drop = FALSE, guide = guide_legend(reverse = TRUE))

  • Related