Search code examples
rggplot2dplyrtidyversegeom-text

Conditional labeling and manual manipulation of labels in geom_text in R


Could anyone help me figure out how to:

  1. Use geom_text to show labels only for those down and up categories (how to remove stable labels)
  2. How to manually change negative labels to positive ones (erase minus sign from negative labels)
  3. How efficiently use hjust to nudge positive labels to right and negative ones to left of the bars (I try something but wonder if there is better way than just doing it for all data one-by-one)

My desired output would be like this one below: enter image description here

Code:

x <- LETTERS[1:11]
y <- c(9, 4, 6, 8, 5, 7, -9, -4, -6, -8, -5)
z <- seq(-1, 1, by = 0.2)

dat <- data.frame(x, y, z)

dat %>%
  filter(x != "B") %>%
  ggplot(aes(fct_reorder(x, y, .desc = T), y, 
             fill = ifelse(z > 0.7, "up", 
                           ifelse(z < -0.6, "down", "stable")))) +
  geom_col() +
  scale_fill_manual("Color", 
                    values = c("up" = "#5b3b71", 
                               "down" = "#9a4054", 
                               "stable" = "#b7c1bd")) +
  geom_text(aes(label = paste0(y,"%")), 
            hjust = c(-1,-1,-1,-1,-1,1,1,1,1,1)) +
  coord_flip() +
  theme_void()

Any help and advice would be much appreciated.


Solution

    1. Filter them out and preprocess all of your dat for this.
    2. Use abs() in geom_text()
    3. same as 1

    try this:

    library(dplyr)
    library(ggplot2)
    library(forcats)
    x <- LETTERS[1:11]
    y <- c(9, 4, 6, 8, 5, 7, -9, -4, -6, -8, -5)
    z <- seq(-1, 1, by = 0.2)
    
    dat <- data.frame(x, y, z) |> 
      mutate(fill_col = ifelse(z > 0.7, "up", 
                               ifelse(z < -0.6, "down", "stable")),
             just_text = ifelse(z > 0, 1, 0)) |> 
      filter(x != "B")
    
    dat %>%
      ggplot(aes(fct_reorder(x, y, .desc = T), y, 
                 fill = fill_col)) +
      geom_col() +
      scale_fill_manual("Color", 
                        values = c("up" = "#5b3b71", 
                                   "down" = "#9a4054", 
                                   "stable" = "#b7c1bd")) +
      geom_text(
        data = dat |> filter(fill_col != "stable"),
        aes(label = paste0(abs(y),"%"), hjust = just_text)) +
      coord_flip() +
      theme_void()
    

    outcome is:

    enter image description here