Skip to content
R for the Rest of Us Logo

Text and Labels

This lesson is locked

Get access to all lessons in this course.

Transcript

Click on the transcript to go to that point in the video. Please note that transcripts are auto generated and may contain minor inaccuracies.

Your Turn

Complete the text and labels sections of the data-visualization-exercises.Rmd file.

Learn More

text and labels Resources

Data Visualization: A Practical Introduction has a section in Chapter 5 on adding text to plots, as does Chapter 28 of R for Data Science.

Information about using vjust and hjust is on the geom_label page of the tidyverse website.

Also, check out the ggrepel package , which automatically adjusts overlapping text and labels.

Have any questions? Put them below and we will help you out!

You need to be signed-in to comment on this post. Login.

Catherine Roller White

Catherine Roller White

April 10, 2021

When I rounded the value labels for average number of hours of sleep, they displayed as 7 and 6.9. I like to keep the number of decimals displayed consistent, even if the decimal is equal to zero. How can I round to one decimal but have 7.0 display as 7.0 instead of 7? Thank you.

Eduardo Rodriguez

Eduardo Rodriguez

April 11, 2021

Hi Catherine, I have the same preference! I investigated further and you can wrap the round function with a format function to keep your preferred number of digits. For example: geom_text(aes(label = format(round(avg_sleep, 1), nsmall = 1))). Here is a link with more info: https://stackoverflow.com/questions/42105336/how-to-round-a-number-and-make-it-show-zeros.

David Keyes

David Keyes

April 12, 2021

That's a great solution, Eduardo! Another way to do this is using the scales package. I recorded a video to show you how it works.

Eduardo Rodriguez

Eduardo Rodriguez

April 13, 2021

Thanks David! Appreciate the additional recommendation of creating two variables, one for values and one for text.

Catherine Roller White

Catherine Roller White

April 13, 2021

Thank you both, Eduardo and David -- very helpful!

Harold Stanislaw

Harold Stanislaw

April 13, 2021

I used sprintf, which also eliminates the need to run a separate "round" calculation (as does Eduardo's approach):

ggplot(data=sleep_by_gender, mapping=aes(x=gender, y=mean_sleep_hrs_night, fill=gender)) + geom_col() + scale_fill_brewer(palette="Paired") + scale_y_continuous(limits = c(0,8), breaks = c(0,1,2,3,4,5, 6, 7, 8)) + geom_text(aes(label = sprintf('%0.1f',mean_sleep_hrs_night),vjust=1),color="white")

Catherine Roller White

Catherine Roller White

April 14, 2021

Thank you, Howard!

Tatiana Bustos

Tatiana Bustos

July 29, 2022

Hm this code is not working for me. Did you need to install sprintf? I'm trying to note alternate codes. If on your GitHub, let me know!

David Keyes

David Keyes

July 31, 2022

You shouldn't need to download anything. What error message did you get?

Megan Ruxton

Megan Ruxton

April 14, 2021

If I have a bar chart with a frequency on the y axis, how do I apply the geom_text and geom_label? For example, in my project I begin with the following code: ggplot(data = intro_etc, aes(x = gender_identity, fill = gender_identity))+ geom_bar() So there isn't anything listed for the y axis for me to enter into the command for geom_text or geom_label.

David Keyes

David Keyes

April 14, 2021

If you're using what I call the v1 bar chart method (i.e. having it calculate counts for you), the default y axis label will be "count." You can still change this by adding labs(y = "Your better label"). Let me know if that answers your question!

Lisa Janz

Lisa Janz

May 11, 2021

The colour of the text keeps turning up red rather than white. I have tried with other colours, but none of them work. I also tried ordering the code the way that it was done in the solutions. Any suggestions as to why this is happening? Is there a library that I haven't loaded? I will also note that in the legend there is a spot for "colour", so it looks like the program has coded colour as a variable. ggplot(sleep_by_gender, mapping = aes(x = gender, y = avg_sleep, fill = gender)) + geom_col() + scale_fill_manual(values = c("yellow", "orange"))+scale_y_continuous(breaks = c(seq(from = 0, to = 8, by = 1))) + geom_text (aes(label = round(avg_sleep, 1), vjust = 1.5, colour = "white"))

Lisa Janz

Lisa Janz

May 11, 2021

Also, you use a totally different code to round the digits than you did in the video. The one that you use in the video seems really unwieldy and I am not sure that I understand it. Can you please explain?

David Keyes

David Keyes

May 11, 2021

Sure, let me know if this video helps explain!

Tatiana Bustos

Tatiana Bustos

July 29, 2022

I had the same question - this is helpful.

Lisa Janz

Lisa Janz

May 11, 2021

Yes, thanks... both of these are helpful videos. I appreciate it.

Lisa Janz

Lisa Janz

May 11, 2021

To position the labels in this exercise, you use vjust = -1.1

Negative and positive values were not discussed in the video and if I use -1.1, the label disappears from the graph. Can you clarify? Is this just a mistake in the tutorial or is my graph too small. What do the numbers represent? Are they related to the width of bins?

David Keyes

David Keyes

May 11, 2021

Let me know if this video helps!

Lisa Janz

Lisa Janz

May 11, 2021

Cool! Thanks. That's interesting. I like the nudge option.

Will there be any tutorials on how to use Help files? I've yet to successfully use one. I entered ?geom_text into the console and got to the help file but have no idea where I'm supposed to put the relevant code and not confident that I know how to parse what it's telling me. For this specific task, I added :show.legend = FALSE: to the very end of my code, but that just removed an "a" within the label. How was I supposed to know from only reading the Help file that I needed put it in 2 places?

sleep_by_gender% mutate(avg_sleep = round(avg_sleep, 1)) ggplot(data=sleep_by_gender, mapping=aes(x=gender, y=avg_sleep, fill=gender))+ geom_col()+ scale_color_brewer(type = "div", palette = "PuOr")+ scale_y_continuous(limits = c(0, 8), breaks = c(0, 1, 2, 4, 6, 8))+ geom_label(aes(label=avg_sleep), vjust= -.5, color= "white", show.legend = FALSE)

David Keyes

David Keyes

October 11, 2021

This is a great question! It actually makes me think that a blog post/video on the topic of reading help files would be useful. I'll work on putting something together. For now, though, the best resource is this section from Kieran Healy's Data Visualization book.

David Keyes

David Keyes

October 11, 2021

On your specific question, you should only need to put the show.legend within the geom_col(). The reason that's the case is that ggplot will attempt to show the bars as your legend because that's where the associated aesthetic property (i.e. the fill that shows up within the bars) exists. You shouldn't need to show it in geom_label(). Let me know if that makes sense or if it would helpful to have me make a short video walkthrough.

Jay Cutler

Jay Cutler

March 4, 2022

Hi David, with your code here...

geom_text(aes(label = round(avg_sleep, 1)), vjust = 1.5, color = "white")

My intuitive way of typing the code was to include the 'vjust' and 'color' arguments within the aesthetics parenthetical, like so:

geom_text(aes(label = round(avg_sleep, 1), vjust = 1.5, color = "white"))

...which largely worked, but my text was a strange pink color instead of white. I'm curious why this is the case? Any rhyme or reason to distinguish between what arguments end up with the 'label' piece in the aesthetics parenthetical and what arguments live freely in the geom_text function? Thanks!

Charlie Hadley

Charlie Hadley

March 4, 2022

Hi Jay! This is a great question. I recorded a short video about why colors provided inside aes() don't behave as expected, and here's the code I wrote.

Please do come back if you have follow up questions. Cheers, Charlotte.

Jay Cutler

Jay Cutler

March 4, 2022

Thanks, Charlotte! That's a helpful walkthrough. To confirm my understanding here -- a scale inside the aes() is almost like a new variable; the major components inside aes() are setting up the main skeleton or pieces of the chart (in this case, labels). Once those labels are properly 'defined', future modifications take place outside aes(). Does that sound accurate to you? Thanks for your help!

Charlie Hadley

Charlie Hadley

March 7, 2022

Hi Jay! This is an accurate understanding of what's happening. However, I'm going to advise slightly different terminology which will hep as (or if) you start to handle more complex R. Instead of "variable" the aesthetics that are created by aes() can also be thought of as "coordinate systems", so most charts have an x and y coordinate system[1] but they also contain "fill" and "color" coordinate systems. The behaviour of these coordinate systems is controlled with scale_fill_() or scale_color_() functions, and the guides (legends) for these coordinate systems are controlled with the guide() function.

[1] charts created with geom_sf() do contain x and y coordinate systems, but they're not in standard cartesian geometry. Instead their in the coordinate system of the CRS, which is controlled with coord_sf().

Jay Cutler

Jay Cutler

March 7, 2022

Thank you for your in-depth reply! Definitely helpful as I get used to the language of R.

Tatiana Bustos

Tatiana Bustos

July 29, 2022

Thanks for this discussion! I think this is the most challenging aspect to grasp - the sequencing of specific functions and aes, but this explanation made a lot of sense in viewing the aes essentially as the "builder" of the scale/coordinate system

Zaynaib Giwa

Zaynaib Giwa

April 1, 2022

Hello everyone, For some reason, I can't get the text to turn white. Hopefully, I can get a second pair of eyes on my code. It changes the color to the fill color of female.

ggplot(sleep_by_gender, aes(x=gender, y=avg_sleep, fill=gender)) + geom_col() + scale_y_continuous(limits=c(0,8), breaks = c(0,1,2,3,4,5,6,7,8)) + geom_text(aes(label = round(avg_sleep,1), vjust = 1, color = "white"

            )
        )

Zaynaib Giwa

Zaynaib Giwa

April 1, 2022

Nevermind. I saw someone else already asked this question. I took a look at Charlie's video and it cleared everything up for me. Since I was calling color= white inside of aes it was creating a new scale which lead to that unexpected behavior.

Jordan Helms

Jordan Helms

April 6, 2022

Why do we have to turn the legend off in two places?

Charlie Hadley

Charlie Hadley

April 7, 2022

Hi Jordan! Hopefully this video explains why. Thanks, Charlie

Why have you added the following code line: na.value = "blue"

Charlie Hadley

Charlie Hadley

April 13, 2022

In this specific example the na.value argument of scale_fill_brewer() doesn't have any impact on this data visualisation as there are no NA values in the dataset. If there were NA values then this colour would be used.

Niger Sultana

Niger Sultana

May 24, 2022

Hi I wanted to add superscript, subscript as label on x axis through ggtext package? for example, WD (mg mm-3), -3 will be superscript in R script and Markdown file? or will this work : geom_text(aes(label = paste(WD, (mg)"^(",-3 , ")", sep = "")), parse = TRUE)

Thanks in advance.

Charlie Hadley

Charlie Hadley

May 25, 2022

Hi Niger!

The {ggtext} package requires you to use HTML to create both super and subscript, eg

library(palmerpenguins)
library(tidyverse)
library(ggtext)

penguins %>% 
  ggplot(aes(x = bill_length_mm * bill_depth_mm,
             y = body_mass_g)) +
  geom_point() +
  labs(x = "Bill area (mm<sup>2</sup>)",
       title = "Title with subscript, eg A<sub>1</sub>") +
  theme(axis.title.x = element_markdown(),
        plot.title = element_markdown())

Kirstin O'Dell

Kirstin O'Dell

October 19, 2022

To turn the legend off I used theme (legend.position = "none") and it worked. I wondered if there was a difference between using that code and the way you showed it?

Charlie Hadley

Charlie Hadley

October 19, 2022

Hi Kristin,

There's at least 3 different ways to turn off legends in {ggplot2}! They all achieve the same thing, but sometimes it might be more convenient to write one than another simply because of the code you've already written.

Cheers, Charlie