Adam_G
Adam_G

Reputation: 7879

Cannot conditionally make axis labels bold in ggplot

I am trying to make select axis labels bold, based on a conditional from a different column. In the code below, if Signif equals 1, then the Predictor axis text should be bold. In addition, the segments should appear in the order of Values increasing value.

However, this code is not changing any of the the axis texts to bold.

library(tidyverse)
library(ggtext)
library(glue)

df <- tibble(Predictor = c("Blue","Red","Green","Yellow"),
             Value = c(1,3,2,4),
             Signif = c(0,1,0,1))

df <- df %>% mutate(Predictor = ifelse(Signif==1,
                                 glue("<span style = 'font-weight:bold'>{Predictor}</span>"),
                                 glue("<span style = 'font-weight:plain'>{Predictor}</span>"))
)

df %>% 
  arrange(desc(Value)) %>% 
  mutate(Predictor=factor(Predictor, 
                          levels=df$Predictor[order(df$Value)])) %>%
  ggplot(aes(x=Predictor, y=Value)) +
  geom_segment(aes(xend=Predictor, yend=0)) +
  theme(axis.text.x = element_markdown())

enter image description here

If instead I use element_text() in the last line, and skip the mutate to markdown step above:

df %>% 
  arrange(desc(Value)) %>% 
  mutate(Predictor=factor(Predictor, 
                          levels=df$Predictor[order(df$Value)])) %>%
  ggplot(aes(x=Predictor, y=Value)) +
  geom_segment(aes(xend=Predictor, yend=0)) +
  theme(axis.text.x = element_text(face = if_else(df$Signif==1, "bold", "plain"))) 

It bolds the 2nd and 4th axis label, which corresponds to the Signif equals 1 in the original df.

enter image description here

How can I get the correct axis text labels to appear in bold?

Upvotes: 2

Views: 662

Answers (3)

tjebo
tjebo

Reputation: 23747

All nice answers. The deeper underlying issue however is (not exactly) "hidden" in the warning that comes when you use a vector in a theme element (see plot below).

Your original plot code would work if you would first rearrange your data frame (and re-assign it!) - see code below. I do not encourage that - ggtext::element_markdown was designed exactly with the idea in mind to avoid the use of vectors in theme.

library(tidyverse)

df <- tibble(Predictor = c("Blue","Red","Green","Yellow"),
             Value = c(1,3,2,4),
             Signif = c(0,1,0,1))


df <- arrange(df, Predictor)
df %>% 
  arrange(desc(Value)) %>% 
  mutate(Predictor=factor(Predictor, 
                          levels=df$Predictor[order(df$Value)])) %>%
  ggplot(aes(x=Predictor, y=Value)) +
  geom_segment(aes(xend=Predictor, yend=0)) +
  theme(axis.text.x = element_text(face = if_else(df$Signif==1, "bold", "plain"))) 
#> Warning: Vectorized input to `element_text()` is not officially supported.
#> ℹ Results may be unexpected or may change in future versions of ggplot2.

Created on 2023-01-29 with reprex v2.0.2

Upvotes: 1

stefan
stefan

Reputation: 124148

The issue is that ggtext currently supports only a limited set of CSS properties. From the docs

The CSS properties color, font-size, and font-family are currently supported.

But if you just want to have bold text the answer by @zephryl is the way to go or as a second option use markdown, i.e. wrap inside **:

library(ggplot2)
library(dplyr)
library(ggtext)
library(glue)

df <- df %>%
  mutate(Predictor = ifelse(Signif == 1,
    glue("**{Predictor}**"),
    Predictor
  ))

df %>%
  arrange(desc(Value)) %>%
  mutate(Predictor = factor(Predictor,
    levels = df$Predictor[order(df$Value)]
  )) %>%
  ggplot(aes(x = Predictor, y = Value)) +
  geom_segment(aes(xend = Predictor, yend = 0)) +
  theme(axis.text.x = element_markdown())

enter image description here

Upvotes: 3

zephryl
zephryl

Reputation: 17079

I would’ve expected your code to work honestly, but you can use <b> instead of <span style...>:

library(tidyverse)
library(ggtext)
library(glue)

df <- df %>% 
  mutate(Predictor = ifelse(Signif==1,
                            glue("<b>{Predictor}</b>"),
                            Predictor))

df %>% 
  arrange(desc(Value)) %>% 
  mutate(Predictor=factor(Predictor, 
                          levels=df$Predictor[order(df$Value)])) %>%
  ggplot(aes(x=Predictor, y=Value)) +
  geom_segment(aes(xend=Predictor, yend=0)) +
  theme(axis.text.x = element_markdown())

Upvotes: 5

Related Questions