2
votes

I have a very basic ggplot:

library(ggplot)

ggplot(mpg, aes(x=displ, y=manufacturer)) +
  geom_point() +
  geom_rect(aes(xmin=1.8, xmax=3.0, ymin='audi', ymax='audi', fill='red')) 

I'd like to add a bar from x axis values 1.8 to 3.0 only for the audi row on the y axis. Is there a way to achieve this in ggplot? Any help others can offer on this question would be greatly appreciated!

2
Could you mock up what your expected output is? Either in paint / preview or by manually specifying the coordinates?Ian Campbell

2 Answers

6
votes

It can be done. Categorical values are converted to integers for plotting, so you can either specify them as integers (audi is the first category, so integer is 1), or, as I've done below, make a list of the category names and specify by name.

library(ggplot)
data("mpg")
man_list <- unique(mpg$manufacturer)

ggplot(mpg, aes(x=displ, y=manufacturer)) +
  geom_point() +
  # geom_rect(aes(xmin=1.8, xmax=3.0, ymin= "audi", ymax=lead("audi"), fill='red')) 
  geom_rect(aes(ymin = which(man_list=="audi")-0.5,
                ymax = which(man_list=="audi")+0.5,
                xmin=1.8,
                xmax=3,
                fill="red"))

enter image description here

4
votes

Building on @Greg's answer, I believe it is is safer to recreate the factor levels in the aes call in geom_rect. This is because it is the factor levels rather than the character strings that are coerced to integer.

ggplot(mpg, aes(x=displ, y=manufacturer)) +
  geom_point() +
  geom_rect(aes(ymin = which(levels(as.factor(manufacturer))=="audi") -0.5,
                ymax = which(levels(as.factor(manufacturer))=="audi") +0.5,
                xmin=1.8,
                xmax=3,
                fill="red"))

enter image description here

This works even if the factor levels have been altered from default:

my.mpg <- mpg
my.mpg$manufacturer <-as.factor(my.mpg$manufacturer)
my.mpg$manufacturer <-factor(my.mpg$manufacturer,
                             levels = rev(levels(my.mpg$manufacturer)))
ggplot(my.mpg, aes(x=displ, y=manufacturer)) +
  geom_point() +
  geom_rect(aes(ymin = which(levels(as.factor(manufacturer))=="audi") -0.5,
                ymax = which(levels(as.factor(manufacturer))=="audi") +0.5,
                xmin=1.8,
                xmax=3,
                fill="red"))

enter image description here

In contrast, the which(unique(...)) method fails:

man_list <- unique(my.mpg$manufacturer)

ggplot(my.mpg, aes(x=displ, y=manufacturer)) +
  geom_point() +
  # geom_rect(aes(xmin=1.8, xmax=3.0, ymin= "audi", ymax=lead("audi"), fill='red')) 
  geom_rect(aes(ymin = which(man_list=="audi")-0.5,
                ymax = which(man_list=="audi")+0.5,
                xmin=1.8,
                xmax=3,
                fill="red"))

enter image description here