Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stacked Bar Graph using ggplot with Negative Values in R

Tags:

r

ggplot2

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. :)

like image 996
Srivats Chari Avatar asked Oct 24 '25 03:10

Srivats Chari


2 Answers

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))

like image 134
stefan Avatar answered Oct 26 '25 18:10

stefan


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

like image 26
TarJae Avatar answered Oct 26 '25 16:10

TarJae



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!