Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding discrete x axis labels in a fool-proof way to avoid mismatching labels & data

Tags:

r

ggplot2

Say I have a barplot with x axis labels that I want to replace. How can I map the new label values to the old ones in order to ensure correct labeling and no mismatch of labels & bars?

In ggplot2, editing the x axis labels can be done using the labels argument in scale_x_discrete(). By passing a vector with strings to labels, we can control both the content of the labels and their order. However, when creating the labels vector, one might mistakenly write the labels in the wrong order, thus mismatching labels and data in a way that might go unnoticed, but in fact creates a wrong figure.

Is there a way to avoid such danger by specifying which new label matches each old label?

Example

library(ggplot2)

p <- ggplot(PlantGrowth, aes(x = group, y = weight, fill = group)) +
     geom_bar(stat = "identity")

> p

barplot

Now let's say I want to replace the set of labels on the x axis

My alternative set of labels is
ctrl -> moon
trt1 -> sun
trt2 -> stars
p + scale_x_discrete(labels = c("sun", "moon", "stars")

moon_sun_stars

Yikes! I mistakenly wrote out the labels vector in the wrong order. It was supposed to be c(moon, sun, stars) and not c(sun, moon, stars). Such error could easily go unnoticed, and make the plot wrong. Is there a way to map new labels to old labels more directly? Analogously to how dplyr::rename closely specifies new_val = old_val for each variable? Then, such mismatching is less likely to happen.

like image 263
Emman Avatar asked Sep 07 '25 04:09

Emman


1 Answers

Of course you can. You can use named vectors to assign new labels and values like so:

library(ggplot2)

p <- ggplot(PlantGrowth, aes(x = group, y = weight, fill = group)) +
  geom_bar(stat = "identity")

p + 
  scale_x_discrete(labels = c(ctrl = "moon", trt1 = "sun", trt2 = "stars")) +
  scale_fill_manual(labels = c(ctrl = "moon", trt1 = "sun", trt2 = "stars"),
                    values = c(ctrl = "blue", trt1 = "red", trt2 = "green"))

Instead of recoding inside scale_xxx_xxx my preferred approach would be to pre-define the vectors for the labels and values outside of the ggplot call to reduce the code duplication and makes it easier to change the labels or values.

labels <- c(ctrl = "moon", trt1 = "sun", trt2 = "stars")
colors <- c(ctrl = "blue", trt1 = "red", trt2 = "green")

p + 
  scale_x_discrete(labels = labels) +
  scale_fill_manual(labels = labels, values = colors)
like image 176
stefan Avatar answered Sep 10 '25 03:09

stefan