Post #21. Useful tips for mapping color and fill aesthetic in the same geom layer

2022

In this quick post, I will show you how to use color and fill aesthetic together in the same geom layer to achieve the desired outcome!

Gen-Chang Hsu
2022-10-22

Background

Color and fill aesthetic often come hand in hand in ggplots, and knowing how to use them together will be handy and save lots of your time searching the internet. In this quick post, I will use a simple boxplot example to demonstrate their use.

Various mappings of color and fill aesthetics

The boxplot below shows the sepal length of the three species in the iris dataset, with box lines colored by species:

library(tidyverse)

ggplot(iris, aes(x = Species, y = Sepal.Length)) + 
  geom_boxplot(aes(color = Species)) +
  scale_color_brewer(palette = "Set1") + 
  labs(x = "Species", y = "Sepal length") + 
  theme_classic(base_size = 13)

Suppose that we want to fill the boxes by species too. We can do this by specifying fill = species in aes() and adding scale_fill_brewer(palette = "Set1"):

ggplot(iris, aes(x = Species, y = Sepal.Length)) + 
  geom_boxplot(aes(color = Species, fill = Species)) +
  scale_color_brewer(palette = "Set1") + 
  scale_fill_brewer(palette = "Set1") +
  labs(x = "Species", y = "Sepal length") + 
  theme_classic(base_size = 13)

But there is a shortcut for doing this: using the function after_scale(). So this function will reuse the scale of a previous aesthetic (in this case “color”) for another aesthetic (in this case “fill”) so that the latter aesthetic will follow the scale of the previous one (sounds a bit abstract? See the code and figure below!). Also, with after_scale(), you don’t need to add scale_fill_brewer(palette = "Set1") as what we did in the previous figure.

ggplot(iris, aes(x = Species, y = Sepal.Length)) + 
  geom_boxplot(aes(color = Species, fill = after_scale(color))) + # use "after_scale()" to reuse the scale of color aesthetic for the fill aesthetic
  scale_color_brewer(palette = "Set1") +
  labs(x = "Species", y = "Sepal length") + 
  theme_classic(base_size = 13)

Now, let’s say we want to change the transparency of the box lines. We can do this by applying after_scale() to a second color aesthetic to modify the scale of the first color aesthetic and change its transparency:

ggplot(iris, aes(x = Species, y = Sepal.Length)) + 
  geom_boxplot(aes(color = Species, fill = after_scale(color),
                   color = after_scale(alpha(color, 0.1)))) +  # use "after_scale()" to modify the scale of first color aesthetic
  scale_color_brewer(palette = "Set1") + 
  labs(x = "Species", y = "Sepal length") + 
  theme_classic(base_size = 13)

Likewise, we can apply the same method to the fill aesthetic to change the transparency of the boxes:

ggplot(iris, aes(x = Species, y = Sepal.Length)) + 
  geom_boxplot(aes(color = Species, fill = after_scale(alpha(color, 0.1)))) +  # use "after_scale()" to reuse and modify the scale of color aesthetic for the fill aesthetic
  scale_color_brewer(palette = "Set1") + 
  labs(x = "Species", y = "Sepal length") + 
  theme_classic(base_size = 13)

Note that you can also change the transparency of the boxes by directly specifying the “alpha” argument outside aes(). But did you notice the subtle difference from the previous figure? There you go: The outlier point in the bottom right corner has become partially transparent now!

ggplot(iris, aes(x = Species, y = Sepal.Length)) + 
  geom_boxplot(aes(color = Species, fill = after_scale(color)), alpha = 0.1) +
  scale_color_brewer(palette = "Set1") + 
  labs(x = "Species", y = "Sepal length") + 
  theme_classic(base_size = 13)

Summary

To recap, we learned how to use the function after_scale() to tweak the color and fill aesthetic in the same geom layer. As its name suggests, this function reuses the scale of an aesthetic for another aesthetic after the mapping of the first aesthetic, or modifies the scale of an aesthetic after the first mapping of that aesthetic.

Hope you learn something useful from this post and don’t forget to leave your comments and suggestions below if you have any!

Corrections

If you see mistakes or want to suggest changes, please create an issue on the source repository.