10

I recently upgraded to R version 3.2.3 and also to ggplot version 2.0.0.

Trying to upgrade some old code to the newer versions I encountered a weird behaviour with ggplot2 and its transparency settings.

Now my question is, is this a bug or a feature (if so, can someone enlighten me as to why its good to have it this way)? The result I want to have is (obviously) plot 2.

Say I plot a line and lay a rectangle with transparency over it like this:

library(ggplot2)

plot_data <- data.frame(x = 1:100, y = rnorm(100))

# Plot 1
ggplot(data = plot_data, aes(x = x, y = y)) + 
  geom_line() + 
  geom_rect(aes(xmin = 20, xmax = 50, ymin = -Inf, ymax = Inf), fill = "red", 
            alpha = 0.1) + ggtitle("Plot 1")

# Plot 2
ggplot() + 
  geom_line(data = plot_data, aes(x = x, y = y)) + 
  geom_rect(aes(xmin = 20, xmax = 50, ymin = -Inf, ymax = Inf), fill = "red", 
            alpha = 0.1) + ggtitle("Plot 2")

To my understanding plot 1 and 2 should be identical. However, I get the following plots:

Plot 1:

Plot1

and plot 2:

Plot2

Additionally, if I play around with the alpha-values (for example setting them to 0.01, I get the two following plots:

Plot1a

and

Plot2a

David
  • 9,216
  • 4
  • 45
  • 78
  • 3
    in your plot 2, if you add data = plot_data to your geom_rect() you will get the same results as plot1 – MLavoie Jan 25 '16 at 12:53
  • Which is interesting, but doesn't reflect an alpha of 0.1 (quite transparent) to my understanding! – David Jan 25 '16 at 12:55

1 Answers1

2

I believe that calling geom_rect without a data parameter will effectively draw an individual rectangle for each row of the data.frame which is why the alpha is "working", but not quite as expected. I have not been able to replicate and get to parity/agreement between the methods, but as you noted, I think it is doing something along the lines of drawing either 100 individual rectangles, or 30 (the width of the rectangles; from 20 to 50) which is why alpha = 0.1 / 100 and alpha = 0.1 / 30 gets you closer, but not quite matching.

Regardless, I would probably use annotate, as that better describes the behavior/result you are trying to achieve without issues and works, as expected, in both cases -- annotations will draw a single instance per geom:

ggplot(data = plot_data, aes(x = x, y = y)) + 
  # geom_rect(aes(xmin = 20, xmax = 50, ymin = -Inf, ymax = Inf, alpha = 0.1, fill = "red")) +
  annotate("rect", xmin = 20, xmax = 50, ymin = -Inf, ymax = Inf, alpha = 0.1, fill = "red") +
  geom_line() + 
  ggtitle("Plot 1")

ggplot() + 
  geom_line(data = plot_data, aes(x = x, y = y)) + 
  # geom_rect(aes(xmin = 20, xmax = 50, ymin = -Inf, ymax = Inf), fill = "red", alpha = 0.1) + 
  annotate("rect", xmin = 20, xmax = 50, ymin = -Inf, ymax = Inf, fill = "red", alpha = 0.1) +
  ggtitle("Plot 2")
JasonAizkalns
  • 20,243
  • 8
  • 57
  • 116
  • Drawing 1 rectangle for each row is probably what's causing it, at least it sounds plausible to me! – David Jan 25 '16 at 13:55
  • @David found a [similar question here](http://stackoverflow.com/q/15903868/2572423) that alludes to the same logic/reasoning; it still bothers me that I cannot get them to "match". – JasonAizkalns Jan 25 '16 at 13:58
  • I also stumbled upon this [question](http://stackoverflow.com/questions/17521438/geom-rect-and-alpha-does-this-work-with-hard-coded-values) that mentions to use just one row in `geom_rect`.. – David Jan 25 '16 at 14:01