It's actually pretty easy to implement this for use in the general case (where you can't hide the lower error bar under another plot element) now that they've made it easy to extend ggplot2
with custom geom
s.
Copy the code from geom_errorbar
from the github repository for ggplot2
into a new .R file. Then make a few modifications, as follows:
geom_uperrorbar <- function(mapping = NULL, data = NULL,
stat = "identity", position = "identity",
...,
na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE) {
layer(
data = data,
mapping = mapping,
stat = stat,
geom = GeomUperrorbar,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
na.rm = na.rm,
...
)
)
}
The only two changes necessary above were to change geom_errorbar
to geom_uperrorbar
and geom = GeomErrorbar
to geom = GeomUperrorbar
.
GeomUperrorbar <- ggproto("GeomUperrorbar", Geom,
default_aes = aes(colour = "black", size = 0.5, linetype = 1, width = 0.5,
alpha = NA),
draw_key = draw_key_path,
Note that this comment is interrupting partway through a function which continues in the code blocks below. Above we just changed GeomErrorbar
to GeomUperrorbar
twice.
required_aes = c("x", "y", "ymax"),
setup_data = function(data, params) {
data$width <- data$width %||%
params$width %||% (resolution(data$x, FALSE) * 0.9)
transform(data,
xmin = x - width / 2, xmax = x + width / 2, width = NULL
)
},
Interrupting the function again. Above we changed the required aesthetics to be x
, y
and ymax
, i.e. replacing ymin
with y
. We need y
to start the vertical line there (instead of at ymin
) and we no longer need ymin
because there's not going to be a horizontal line there.
draw_panel = function(data, panel_scales, coord, width = NULL) {
GeomPath$draw_panel(data.frame(
x = as.vector(rbind(data$xmin, data$xmax, NA, data$x, data$x)),
y = as.vector(rbind(data$ymax, data$ymax, NA, data$ymax, data$y)),
colour = rep(data$colour, each = 5),
alpha = rep(data$alpha, each = 5),
size = rep(data$size, each = 5),
linetype = rep(data$linetype, each = 5),
group = rep(1:(nrow(data)), each = 5),
stringsAsFactors = FALSE,
row.names = 1:(nrow(data) * 5)
), panel_scales, coord)
}
)
Here we removed the last three elements of the vectors passed to x
and y
, which were for the lower error bar. In addition, we changed the last element from ymin
to y
, because we want the line to start at y
, not ymin
.
"%||%" <- function(a, b) {
if (!is.null(a)) a else b
}
This last bit is just a convenience function used in the code that needs to be defined.
If you source the document including all of this code, then you can use geom_uperrorbar
just like geom_errorbar
, or even pass geom = "uperrorbar"
to stat_summary
, using y
instead of ymin
.