Reputation: 437
I am plotting temperature values over the course of a year using geom_smooth()
. I have daily min, max, and mean temperatures, and I would like to display the mean as a line, and then the min and max like you would display a confidence interval. There is a se = T
argument to geom_smooth()
, and I am wondering how I can supply variables to use as the "confidence interval." I know you can do this with box plots with geom_errorbar()
, and I'm hoping there is a similar version for line plots.
I would like my plot to look like the results of this, but using the max and min values to display the confidence interval.
mean <- runif(365, min = 10, max = 25)
max <- runif(365, min = 26, max = 35)
min <- runif(365, min = 0, max = 9)
temp <- data.frame(day = 1:365, mean = mean)
ggplot(data = temp, aes(x = day, y = mean)) +
geom_smooth()
EDIT: I am adding two years of data, and would like each year to have its own geom_smooth line and its own geom_ribbon. As the code is now, each year has its own geom_smooth line but there is a single geom_ribbon for all years.
mean1 <- runif(365, min = 10, max = 25)
max1 <- runif(365, min = 26, max = 35)
min1 <- runif(365, min = 0, max = 9)
mean3 <- runif(365, min = 10, max = 25)
max3 <- runif(365, min = 30, max = 40)
min3 <- runif(365, min = -5, max = 5)
mean2 <- runif(365, min = 10, max = 25)
max2 <- runif(365, min = 200, max = 220)
min2 <- runif(365, min = -10, max = 9)
temp <- rbind(data.frame(day = 1:365, mean = mean1, max = max1, min = min1, label = 'A'),
data.frame(day = 1:365, mean = mean2, max = max2, min = min2, label = 'B'),
data.frame(day = 1:365, mean = mean3, max = max3, min = min3, label = 'C'))
ggplot(data = temp, aes(x = day, y = mean, color = label)) +
geom_ribbon(data = temp %>% group_by(label),
aes(ymin = stats::predict(loess(min ~ day)), ymax = stats::predict(loess(max ~ day)),
color = label),
alpha = 0.1) +
geom_smooth(se = F)
Thanks!
Upvotes: 2
Views: 1070
Reputation: 66415
EDIT #2: See bottom for smoothed ribbon. Adopted from https://stackoverflow.com/a/71423425/6851825
EDIT: 2nd option below uses min
/max
directly to define shaded range.
We could specify a fixed confidence interval by putting the confidence interval into a ribbon layer that uses the stat_smooth
calculation, but where we override the y range to use the smooth value plus a constant.
ggplot(data = temp, aes(x = day, y = mean)) +
stat_smooth(
geom="ribbon",
aes(ymax = after_stat(y) + 1,
ymin = after_stat(y) - 1),
alpha = 0.1
) +
geom_smooth(se = FALSE)
Of if you mean you want to use the min and max values directly as your shaded range:
ggplot(data = temp, aes(x = day, y = mean)) +
geom_ribbon(aes(ymin = min, ymax = max),
alpha = 0.1) +
geom_smooth(se = FALSE)
Adopted from https://stackoverflow.com/a/71423425/6851825,
we can put the min and max into the data frame and make a ribbon that calls predict(loess(y~x))
to calculate the min and max ranges.
temp <- data.frame(day = 1:365, mean = mean,
max = max, min = min)
ggplot(data = temp, aes(x = day)) +
geom_ribbon(alpha = 0.1,
aes(ymin = predict(loess(min~day)),
ymax = predict(loess(max~day)))) +
geom_smooth(aes(y = mean), se = FALSE) +
# these are to confirm the ranges match what geom_smooth would produce
geom_smooth(aes(y = max), se = FALSE, linetype = "dashed", size = 0.2) +
geom_smooth(aes(y = min), se = FALSE, linetype = "dashed", size = 0.2)
EDIT based on new grouped data:
The prior technique doesn't work with grouped data because the base predict
function doesn't "see" groups unless we've put it inside dplyr::group_by
and dplyr::mutate
. So we can use those to precalculate the values we need in the data =
part.
ggplot(data = temp, aes(x = day, y = mean, color = label)) +
geom_ribbon(data = temp %>% group_by(label) %>%
mutate(ymin_smooth = stats::predict(loess(min~day)),
ymax_smooth = stats::predict(loess(max~day))),
aes(ymin = ymin_smooth, ymax = ymax_smooth, fill = label),
alpha = 0.1) +
geom_smooth(se = F)
Upvotes: 3