Coloured text in {ggplot2}: {ggtext} vs {marquee}
An alternative to a traditional legend is using coloured text in a subtitle. In {ggplot2}, we can do this using the {ggtext} package. You can also do it using the new {marquee} package. How do they compare?
June 4, 2024
When you use colour to denote the values of a variable in a visualisation, it’s very common to add a legend showing how the colours map to different values. If you create your charts using {ggplot2}, a legend is added automatically when you add colour
or fill
within the aesthetic mapping.
One problem with these legends is that they take up a lot of space - space where we could be plotting data instead! An alternative to using a traditional legend, is using coloured text within a subtitle or annotation.
Note: this approach works well when the colours are used for categorical data, but not so well for continuous colour scales.
As an example, let’s go back to our favourite animal dataset. No, not penguins - though they are a close second! We’re looking at lemur data from Duke Lemur Center. The data was used as a #TidyTuesday dataset back in 2021 so we can load it in from the CSV file on GitHub:
|
|
Alternatively, you could load it using the {tidytuesdayR} R package.
I’ve used this data several times for teaching, and in a previous blog post about using both R and Python in Quarto documents.
Let’s do a quick bit of data wrangling using {dplyr}, by filtering to look at only adult,
collared brown lemurs, keeping only the columns we need (weight, age, and sex), renaming thos columns with slightly nicer looking variable names, and recoding the "M"
and "F"
values in Sex
as "male"
and "female"
:
|
|
Click here for a bonus lemur photo!
Image:unsplash.com/photos/gray-and-white-cat-on-brown-floor-6OFUMVoRdq4
Now we can create a simple scatter plot using geom_point()
in {ggplot2}, by mapping Age
onto the x axis, Weight
onto the y axis, and colouring the points based on Sex
:
|
|
Let’s also add a title and subtitle:
|
|
This looks fine. But let’s use some nicer colours, and use coloured text instead of the legend.
Coloured text with {ggtext}
I mentioned in a recent R for the Rest of Us podacst how I used to use R for the first 95% of my plots but then added annotations and edits using other tools because it was easier. I also mentioned how that’s no longer the case - I now make (almost) 100% of my R visualations in R, and that’s largely down to the {ggtext} package. The {ggtext} package provides simple Markdown and HTML rendering for text in {ggplot2}.
Let’s start by defining a named vector of colours for male and female lemurs:
|
|
For more complicated examples you can, of course, use something like case_when()
to map colours to values to save you from typing out the values.
Now we need to pass these colours into the subtitle text. Let’s create a variable that contains the text, called ggtext_st
. We use HTML code (and a tiny bit of CSS) to format the text with colours. If you’re not familiar with HTML code, an example might look like this:
|
|
We wrap all of the text we want to appear inside <span></span>
tags. Inside the style
option, we pass in CSS options such as color
.
We could manually pass in the text we want to appear in the subtitle:
|
|
However, to make sure that the colours and variables are correctly mapped in the text, we can use the
{glue} package to pass in the variables from col_vec
:
|
|
We can add the colours to our plot using scale_colour_manual()
, and pass our new subtitle into the labs()
function:
|
|
That doesn’t look quite right…
That’s because we haven’t actually used the {ggtext} package yet! We need to tell {ggplot2} that we’re using HTML code in the subtitle. We do this using the theme()
function and setting the plot.subtitle
argument to element_textbox_simple()
. You can also use element_textbox
if you prefer. Another nice feature of element_textbox_simple()
is that long text is automatically wrapped to the width of the plot rather than running off the end! We can also remove the existing legend at the same time:
|
|
I hope you’ll agree that this looks much cleaner and tidier!
See also
geom_richtext()
orgeom_textbox()
as alternatives togeom_text()
.
Coloured text with {marquee}
The recently released {marquee} package provides a markdown parser and renderer for the R graphics engine - meaning it can be used to render more complex markdown text in {ggplot2} graphics.
{marquee} is built for the future so you do need the lastest version of R Graphics engines for it to work.
To add coloured text with Markdown format, we wrap the text to appear in curly brackets. After the opening curly bracket, add a .
and the colour you want to the text to appear:
|
|
As in the previous example with {ggtext}, we can use glue()
to bring the colours and the labels into the subtitle text string. Since the markdown formatting is written inside curly brackets {
and }
, the glue()
function might get confused about which brackets it’s supposed to be using and complain. To avoid this, we’ll tell glue()
to use [
and ]
instead.
|
|
You can alternatively use
marquee_glue()
( see marquee.r-lib.org/reference/marquee_glue.html, to allow you to use curly brackets for both markdown syntax andglue
. I find nested curly brackets harder to read, but that’s just a personal preference and you could use eitherglue::glue()
ormarquee::marquee_glue()
.
Much like {ggtext}, we need to tell {ggplot2}
that we’re using {marquee} to format text, by passing element_marquee()
to the plot.subtitle
argument in theme()
:
|
|
The text wrapping using {marquee} isn’t automatic, but you can set width = 1
to wrap the text.
See also
geom_marquee()
as an alternative togeom_text()
.
Comparing {ggtext} and {marquee}
You can see that though {ggtext} and {marquee} use HTML vs Markdown, respectively, the way you add coloured text isn’t too different - the process is similar. If all you’re doing is adding coloured text, there isn’t much of a reason to choose one over the other - unless you have a strong preference for HTML or Markdown syntax. One benefit of {marquee} is that it doesn’t just work with {ggplot2} - you can also use it with other graphics packages in R. You can read more about {marquee} in the blog post by Thomas Lin Pedersen.
I, for one, am very excited about all of the new text features coming to R through {marquee} - it brings a lot more than just coloured text in subtitles. But {ggtext} still has a special place for me as the package that changed how easy it is to go from the start to finish of a visualisation using only R.
For attribution, please cite this work as:
Coloured text in {ggplot2}: {ggtext} vs {marquee}.
Nicola Rennie. June 4, 2024.
nrennie.rbind.io/blog/coloured-text-legend-ggplot-ggtext-marquee
BibLaTeX Citation
@online{rennie2024, author = {Nicola Rennie}, title = {Coloured text in {ggplot2}: {ggtext} vs {marquee}}, date = {2024-06-04}, url = {https://nrennie.rbind.io/blog/coloured-text-legend-ggplot-ggtext-marquee} }
Licence: creativecommons.org/licenses/by/4.0