'ggplot2 add geom_text on geom_col layer with labels data.frame

I have a bar plot with position = fill to show proportions with 2 colors on the same column. I'm trying to add a geom_text layer on this graph to show ho many genes out of the total genes are making the plotted proportion (e.g. Condition == "UT", Keyword = "Zinc", 3 up 2 down -> proportions 0.6:0.4 of 5 zinc-related genes (Nb_Keyword) out of 131 DE genes in this condition (Nb_Tot) label is then 5 / 131.

I have this code for the plot and ggplot 2 uses twice the Nb_Keyword and Nb_Tot data to make up the label since there are here twice, once with Direction == "Down" and once with Direction == "Up".

Alternatively I tried to use a specific data frame for the aes in geom_text, df_labels, which has half the number of rows of the data frame used for the bar plot. This generates an error because the data of geom_text()'s aes layer is not the same length as the bar plot data.

I did not manage to get the plot I want with annotate() neither. What is the right strategy to do what I want to do?

Thank you for your help! Danielenter image description here

library(ggplot2)

### reconstitute df3
condition <- rep(c("UT", "STV", "AA"), each = 4, times = 2)
keyword <- rep(c("Ribosome", "Zinc", "Predicted_gene", "Pseudogene"), times = 6)
nb_keyword <- rep(c(7,5,9,1,6,0,2,1,18,9,30,12), times = 2)
length(nb_keyword)
nb_tot <- rep(c(131,75,383), each = 4, times = 2)
direction <- rep(c("Down", "Up"), each = 12)
proportion <- c(5,2,6,1,1,0,2,0,6,0,21,6,2,3,4,0,5,0,0,1,12,9,9,6)

df3 <- data.frame(condition, keyword, nb_keyword, nb_tot, direction, proportion)
names(df3) <- gsub("(^|[_[:space:]])([[:alpha:]])", "\\1\\U\\2", names(df3), perl = TRUE)

df3$Condition <- ordered(df3$Condition, levels = c("UT", "STV", "AA"))
df3$Direction <- ordered(df3$Direction, levels = c("Up", "Down"))

df_labels <- df3[c(1:12), c("Condition","Keyword", "Nb_Keyword", "Nb_Tot")]

color_vector <- c(Up = "#2CA913", Down = "#DB0F0F")

# plot
p2 <- ggplot(df3, aes(x = Condition, y = Proportion)) +
  geom_col(aes(fill = Direction), position = "fill") +
  scale_fill_manual(values = color_vector) +
  theme(axis.text.x = element_text(angle=90,hjust = 1, vjust=0.2)) +
  facet_grid(cols = vars(Keyword)) +
  geom_text(aes(x = Condition, label = paste(Nb_Keyword, "/",Nb_Tot)), angle = 90)

p2


Solution 1:[1]

In the aes of geom_text, you cannot use the inherited y value, otherwise the labels would be according to the position in the Proportion column. Instead, you should set geom_text(aes(y)) to a value close to 0. The hjust = 0 argument is to left-align (in this case, bottom-align) the text.

EDIT: Thanks @stefan for improving my answer by adding the check_overlap = TRUE argument to avoid overlapping labels.

library(ggplot2)

ggplot(df3, aes(x = Condition, y = Proportion)) +
  geom_col(aes(fill = Direction), position = "fill") +
  scale_fill_manual(values = color_vector) +
  theme(axis.text.x = element_text(angle=90,hjust = 1, vjust=0.2)) +
  facet_grid(cols = vars(Keyword)) +
  geom_text(aes(y = 0.05, label = paste(Nb_Keyword, "/",Nb_Tot)), angle = 90, hjust = 0, check_overlap = T)

Created on 2022-04-12 by the reprex package (v2.0.1)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1