How to plot data using geom_vline(), geom_text() and aes(colour =)

Hi all,

EDIT: of course 10 minutes after working on this post I found the solution to the problem mysef... Moving colour=cyl from ggplot to geom_point() worked as cyl isn't present in my data frame lines. However, I still don't understand one thing and I would be greatful it you could help me with it: using inherit.aes = F should also do the trick, right? But how do I use it correctly in the example below? Thanks!

I'm having some trouble plotting simple stuff using geom_vline() and geom_text() in conjunction with colour. Part of my question relates to understanding why the following happens: when plotting data and adding vertical lines with some text, if I add colour in aes() R throws an error that the object can't be found. Could you help me understand this behaviour? I've reproduced my problem below using mtcars. (Also, I couldn't think of a better title for this thread. Happy to change it to something more suitable if you have something in mind that describes the problem better).

Say I want to plot two variables and additionally draw two vertical lines meaningful to my project. The lines must have added text. I can achieve this with:

library(tidyverse)

data(mtcars)

groups <- c(1, 3, 4)

lines <- data.frame(vlines = c(2.5, 4), labels = c("Two point five", "Four"), stringsAsFactors = FALSE)

mtcars %>%
  filter(carb %in% groups) %>%
  ggplot(aes(wt, mpg)) +
  geom_point() +
  geom_vline(data = lines, aes(xintercept = vlines)) +
  geom_text(data = lines, aes(x = vlines, y = 0, label = labels))

Created on 2020-04-18 by the reprex package (v0.3.0)

Now let's say I want to do the same but visualising the data by number of cylinders. Tentatively I'd do:

mtcars %>%
  filter(carb %in% groups) %>%
  ggplot(aes(wt, mpg, colour = cyl)) +
  geom_point() +
  geom_vline(data = lines, aes(xintercept = vlines)) +
  geom_text(data = lines, aes(x = vlines, y = 0, label = labels))
#> Error in FUN(X[[i]], ...): object 'cyl' not found

Created on 2020-04-18 by the reprex package (v0.3.0)

As you can see adding colour = cyl makes R complain that cyl isn't there. Same plot without geom_vline() and geom_text() works just fine:

mtcars %>%
  filter(carb %in% groups) %>%
  ggplot(aes(wt, mpg, colour = cyl)) +
  geom_point()


Created on 2020-04-18 by the reprex package (v0.3.0)

I understand that it has to do with using the points and labels for the vertical lines as a data frame, because if I instruct R to draw the lines and their text "manually" on a per-case basis it works just fine:

mtcars %>%
  filter(carb %in% groups) %>%
  ggplot(aes(wt, mpg, colour = cyl)) +
  geom_point() +
  geom_vline(xintercept = 2.5) +
  geom_text(aes(x = 2.5 , y = 0, label = "Two point five")) +
  geom_vline(xintercept = 4) +
  geom_text(aes(x = 4 , y = 0, label = "Four"))


Created on 2020-04-18 by the reprex package (v0.3.0)

However, in my real problem I have a bigger number of lines (and therefore text) to draw, thus I'd like to use a different approach (as in specifying in geom_vline() a data frame with all the info needed to draw the lines and respective text).

Could you explain me why this behaviour occurs and how I could solve it? Thanks so much!

1 Like

Hi ysc,

The argument inherit.aes looks to whether any aesthetics have be set in the
ggplot function so in your example, everything below this will inherit colour = cyl.

The default inherit.aes argument in geom_vline() is set to FALSE, so nothing has
to be added. For geom_text(), the default is set to inherit.aes = TRUE, so this needs to be changed otherwise it will look for cyl in the lines data.frame.

There are a few ways around this.

Using your example data:

library("tidyverse")
data(mtcars)
groups <- c(1, 3, 4)
lines <- data.frame(vlines = c(2.5, 4), labels = c("Two point five", "Four"),
stringsAsFactors = FALSE)
  1. Specify inherit.aes = FALSE in geom_text()
mtcars %>%
      filter(carb %in% groups) %>%
  ggplot(aes(x = wt, y = mpg, color = cyl)) + 
  geom_point() +
  geom_vline(data = lines, aes(xintercept = vlines)) +
  geom_text(data = lines, aes(x = vlines, y = 0, label = labels),
    inherit.aes = FALSE)
  1. Move the aesthetics from ggplot() down to geom_point()
mtcars %>%
      filter(carb %in% groups) %>%
  ggplot() + 
  geom_point(aes(x = wt, y = mpg, color = cyl)) +
  geom_vline(data = lines, aes(xintercept = vlines)) +
  geom_text(data = lines, aes(x = vlines, y = 0, label = labels))

  1. Supply the mtcars data.frame as the data argument in geom_point() and leave ggplot() empty.
ggplot() + 
  geom_point(data = mtcars %>%
      filter(carb %in% groups), aes(x = wt, y = mpg, color = cyl)) +
  geom_vline(data = lines, aes(xintercept = vlines)) +
  geom_text(data = lines, aes(x = vlines, y = 0, label = labels))

Thanks a lot for your reply. Ended up working solutions #1 and #2 by myself, but your 3rd option looks to me more concise (and elegant) than the other two, so thanks!!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.