Reputation: 1631
I have the following code (as an example) which I would like to adapt such that the ribbon extends to the entire xrange, as geom_hline()
does. The ribbon indicates what values are within accepted bounds. In my real application sometimes has no upper or lower bound, so the hline by itself is not enough to determine whether values are within bounds.
library(ggplot2)
set.seed(2016-12-19)
dates <- seq(as.Date('2016-01-01'), as.Date('2016-12-31'), by = 1)
values <- rexp(length(dates), 1)
groups <- rpois(length(dates), 5)
temp <- data.frame(
date = dates,
value = values,
group = groups,
value.min = 0,
value.max = 2
)
ggplot(temp, aes(date, value)) +
geom_ribbon(aes(ymin = value.min, ymax = value.max), fill = '#00cc33', alpha = 0.6) +
geom_hline(aes(yintercept = value.min)) +
geom_hline(aes(yintercept = value.max)) +
geom_point() +
facet_wrap(~group)
I tried setting the x
in geom_ribbon
to dates
as well, but then only fractions of the range are filled.
Also I tried this:
geom_ribbon(aes(ymin = -Inf, ymax = 2, x = dates), data = data.frame(), fill = '#00cc33', alpha = 0.6)
but then the data seems to be overwritten for the entire plot and I get the error Error in eval(expr, envir, enclos) : object 'value' not found
. Even if it would work then the range is still actually too narrow as the xlimits are expanded.
Upvotes: 4
Views: 1669
Reputation: 1631
Based on lukeA's answer I produced the following code, which I think is a little simpler:
library(ggplot2)
set.seed(2016-12-19)
dates <- seq(as.Date('2016-01-01'), as.Date('2016-12-31'), by = 1)
values <- rexp(length(dates), 1)
groups <- rpois(length(dates), 5)
temp <- data.frame(
date = dates,
value = values,
group = groups,
value.min = 1,
value.max = 2
)
bounds <- data.frame(
xmin = -Inf,
xmax = Inf,
ymin = temp$value.min[1],
ymax = temp$value.max[1]
)
ggplot(temp, aes(date, value)) +
geom_rect(
aes(
xmin = as.Date(xmin, origin = '1970-01-01'),
xmax = as.Date(xmax, origin = '1970-01-01'),
ymin = ymin,
ymax = ymax
),
data = bounds,
fill = '#00cc33',
alpha = 0.3,
inherit.aes = FALSE
) +
geom_point() +
facet_wrap(~group)
I created a temporary dataframe containing the bounds for the rectangle, and added inherit.aes = FALSE
since apparently the bounds otherwise overrule the temp
data.frame (still seems a bug to me). By transforming the -Inf
and Inf
to the correct datatype I didn't need the custom labeler (if your dealing with POSIXt
use the correct as.POSIXct/lt
as automatic transformation fails).
Upvotes: 1
Reputation: 54237
Here's one way to do it:
ggplot(temp, aes(as.numeric(date), value)) +
geom_rect(aes(xmin=-Inf, xmax=Inf, ymin = value.min, ymax = value.max), temp[!duplicated(temp$group),], fill = '#00cc33', alpha = 0.6) +
geom_hline(aes(yintercept = value.min)) +
geom_hline(aes(yintercept = value.max)) +
geom_point() +
scale_x_continuous(labels = function(x) format(as.Date(x, origin = "1970-01-01"), "%b %y")) +
facet_wrap(~group)
Note that I used as.numeric(date)
, because otherwise Inf
and -Inf
yield
Error: Invalid input: date_trans works with objects of class Date only
To get date labels for numeric values, I adjusted the scale_x_continuous
labels accordingly. (Although they are not exact here. You may want to adjust it by using the exact dates instead of month/year, or alternatively set manual breaks using the breaks
argument and for example seq.Date
.)
Also note that I used temp[!duplicated(temp$group),]
to avoid overplotting and thus maintaining the desired alpha transparency.
Upvotes: 3