11

This may end up being an expression or call question, but I am trying to conditionally format individual axis labels.

In the following example, I'd like to selectively bold one of the axis labels:

library(ggplot2)

data <- data.frame(labs = c("Oranges", "Apples", "Cucumbers"), counts = c(5, 10, 12))

ggplot(data = data) + 
  geom_bar(aes(x = labs, y = counts), stat="identity")`

No Bolding

There is similar problem here, but the solution involves theme and element_text. I am trying to use axis labels directly.

I can do this manually as below:

breaks <- levels(data$labs)
labels <- breaks
labels[2] <- expression(bold("Cucumbers"))

ggplot(data = data) + 
  geom_bar(aes(x = labs, y = counts), stat="identity") + 
  scale_x_discrete(label = labels, breaks = breaks)

Bolded

But, if I try to do it by indexing instead of typing out "Cucumbers", I get the following error:

breaks <- levels(data$labs)
labels <- breaks
labels[2] <- expression(bold(labels[2]))

ggplot(data = data) + 
  geom_bar(aes(x = labs, y = counts), stat="identity") + 
  scale_x_discrete(label = labels, breaks = breaks)

Which makes sense, because it is not evaluating the labels[2]. But, does anyone know how to force it to do that? Thanks.

Community
  • 1
  • 1
Sealander
  • 3,467
  • 4
  • 19
  • 19

2 Answers2

12

How about

breaks <- levels(data$labs)
labels <- as.expression(breaks)
labels[[2]] <- bquote(bold(.(labels[[2]])))

ggplot(data = data) + 
  geom_bar(aes(x = labs, y = counts), stat="identity") + 
  scale_x_discrete(label = labels, breaks = breaks)

Here we are more explicit about the conversion to expression and we use bquote() to insert the value of the label into the expression itself.

MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • Yes! `bquote` and `.( )` were what I needed. Thanks. Is there a mnemonic for that function name? Backwards quote? – Sealander May 04 '15 at 17:44
  • From the help page, it's "an analogue of the LISP backquote macro" so that's pretty close. – MrFlick May 04 '15 at 17:48
  • @MrFlick How could I do this for multiple items? For example for position 2 and 3? And also could I do this by specifying the factor names, e.g. "Cucumbers" and "Oranges"? Thanks! – Stefan Sep 26 '16 at 02:20
  • @Stefan You might want to ask a new question with a reproducible example that says how your case is different. `labels` basically asks like a list so you can use any of the functions you use to iterate over lists. The order of the labels goes in the order of the breaks so you can look up values in one and index in the other without a problem. – MrFlick Sep 26 '16 at 03:19
2

Another option is to set the font face dynamically with theme, though I'm not sure if this is in any sense a better or worse method than @MrFlick's answer:

breaks <- levels(data$labs)

# Reference breaks by name
toBold = "Cucumbers"

ggplot(data = data) + 
  geom_bar(aes(x = labs, y = counts), stat="identity") + 
  scale_x_discrete(label = labels, breaks = breaks) +
  theme(axis.text.x=
        element_text(face=ifelse(breaks %in% toBold, "bold", "plain")))

# Reference breaks by position
label.index=2

ggplot(data = data) + 
  geom_bar(aes(x = labs, y = counts), stat="identity") + 
  scale_x_discrete(label = labels, breaks = breaks) +
  theme(axis.text.x=
        element_text(face=ifelse(breaks %in% labels[match(label.index, 1:length(breaks))], 
                                 "bold", "plain")))
eipi10
  • 91,525
  • 24
  • 209
  • 285