Search code examples
rggplot2axis-labels

ggplot: modify axis labels with named vector after having applied function


I have a question regarding the modification of axis labels in ggplot. I know that what I am trying to get at can be done via other means (e.g. creating a new column with case_when). My interest is in the approach/concept outlined below.

Let's say I have a discrete variable at the x-axis. In order to get the desired axis labels, the values are 1) modified with a function, and then 2) changed by assigning the values contained in a named vector to the result of the function. I am able to do each of the two steps individually; but how can they be combined? Can this be done?

Again, I am aware that there are other, probably more sane ways, to do this. And the example below doesn't make any substantive sense. I am just curious whether/how this can be done directly in the e.g. scales_x_discrete function. Below I am trying to detail what I mean. The result would be that all Merc labels become Mercedes, and all instances of Hornet become Super Hornet.

library(tidyverse)

labeller_cars <- c("Hornet"="Super Hornet",
                   "Merc"="Mercedes")

mtcars %>% 
  rownames_to_column(var = "name") %>% 
  filter(str_detect(name, regex("Hornet|Merc"))) %>% 
  ggplot()+
  geom_bar(aes(x=name,
               y=disp),
           stat="identity")+
  #here is what I am interested in; this works, but it's only first step
  scale_x_discrete(labels=function(x) str_extract(x, regex("[:alpha:]*")))
  #this is an attempt, but doesn't work.
  # scale_x_discrete(labels=function(x) str_extract(x, regex("[:alpha:]*")) %>% labeller_cars)

Created on 2021-07-24 by the reprex package (v2.0.0)


Solution

  • We could use str_replace_all instead of str_extract

    library(dplyr)
    library(stringr)
    library(ggplot2)
    labeller_cars <- c(".*Hornet.*"="Super Hornet",
                        ".*Merc.*"="Mercedes")
    mtcars %>% 
       rownames_to_column(var = "name") %>% 
       filter(str_detect(name, regex("Hornet|Merc"))) %>% 
       ggplot()+
       geom_bar(aes(x=name,
                    y=disp),
                stat="identity")+
       #here is what I am interested in; this works, but it's only first step
       scale_x_discrete(labels=function(x) str_replace_all(x, labeller_cars)) + 
     theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
    

    -output

    enter image description here


    Or with str_extract, after extracting the substring, use the named vector to match and replace

    labeller_cars <- c("Hornet"="Super Hornet",
                        "Merc"="Mercedes")
    mtcars %>% 
       rownames_to_column(var = "name") %>% 
       filter(str_detect(name, regex("Hornet|Merc"))) %>% 
       ggplot()+
       geom_bar(aes(x=name,
                    y=disp),
                stat="identity")+
       scale_x_discrete(labels=function(x)
          labeller_cars[str_extract(x, regex("[:alpha:]*"))])
    

    -OUTPUT

    enter image description here