3MW (Custom Color Legends)

Guten Tag!

Many greetings from Ulm, Germany. In today's newsletter, I am showing you how to create custom legends for your plot. And you're in luck:

I've already talked about this in a video a couple of weeks ago. So if you're more of a visual person why don't you head over to YouTube, and check out the video there. There’s even a follow-up video so that you can also automate parts of creating this custom legend.

But if reading is more your thing, then feel free to stick around. And as always, you can find the full code on GitHub.

A basic plot

To begin with, we need a basic scatter plot that has a legend. So here's a short code chunk that gives you just that.

Since we've mapped the colors to the body weight of the penguins, we should probably make sure that darker colors are assigned to the higher weights. That is why we add a scale_fill_distiller() layer where we

  • choose a different palette (just because I like this color more) and

  • make sure that the direction is set to 1

Now, this gives us a green color bar.

Let's move it to the top with theme() and make it a little bit larger with the guides() function.

Discrete color legend

Now what if we wanted to have a discrete color legend instead of a continuous one? The one thing you have to tweak to make this happen is to change the guide_colorbar() function with the guide_colorsteps() function. Then, you will immediately see that this does exactly what you want.

Make some room for a new legend

Okay, that was a very easy way to move from a continuous color bar to a discrete version. Soooo, what about other legends? Maybe you are not quite satisfied with the current look and want to have some padding between the colored rectangles.

In this case, you will have to draw the rectangles manually. Let's do that together. First, we get rid of the legend altogether by setting legend.position = "none" in the theme() function.

Additionally, by adding some margin below the title in the theme() function you can make some room for your legend. Otherwise, ggplot would simply use all of the space for the scatter plot.

(sorry about the image size here - for technical reasons I had to make everything a bit smaller in this newsletter format 😅)

Use annotations to create the legend

Next, we can use annotate() to draw your legend into this new white space. Basically, you need

  • a tile annotation for the colored rectangles,

  • a text annotation for the weight labels and

  • another text annotation for the title of the legend

We start by adding in the rectangles. First, we set the coordinates and the width of the rectangles. Here, I've chosen the coordinates and the width so that rectangles are equally spaced with some padding between them (the YT video gives you more details on the math).

Notice that you haven't actually put the rectangles into the free space below the plot title. That's because the y-axis simply extended. To avoid this, set the axis limits in coord_cartesian() and enable to draw outside the plotting area by setting clip = 'off'.

Then, you will also have to find the correct fill colors of those rectangles. To do so, use brewer.pal() from the RColorBrewer package to extract the colors from the palette that we used to map the weights to color.

Finally, adding the text annotations is pretty straightforward. It's mostly playing around with the x and y coordinates of the labels that you want to place. If you do all of that, your code will look like this:

And you will get a chart that has a pretty neat legend:

Finally, let me point out that you can find more details on how to create this in the video that I've uploaded to YouTube. In there, you will even find a part that explains how to build a third legend that looks like this:

Feel free to check that out if you want. I’ve also created a follow-up video so that you can even automate parts of creating this custom legend.

Hope you’ve enjoyed this week’s newsletter. If you want to reach out to me, just reply to this mail or find me on Twitter, uhhh I mean X.

See next week,
Albert 👋

If you like my content, you may also enjoy these:

Reply

or to participate.