#' Ribbons and area plots.
#'
#' For each continuous x value, \code{geom_interval} displays a y interval.
#' \code{geom_area} is a special case of \code{geom_ribbon}, where the
#' minimum of the range is fixed to 0.
#'
#' An area plot is the continuous analog of a stacked bar chart (see
#' \code{\link{geom_bar}}), and can be used to show how composition of the
#' whole varies over the range of x. Choosing the order in which different
#' components is stacked is very important, as it becomes increasing hard to
#' see the individual pattern as you move up the stack.
#'
#' @section Aesthetics:
#' \Sexpr[results=rd,stage=build]{animint2:::rd_aesthetics("geom", "ribbon")}
#'
#' @seealso
#' \code{\link{geom_bar}} for discrete intervals (bars),
#' \code{\link{geom_linerange}} for discrete intervals (lines),
#' \code{\link{geom_polygon}} for general polygons
#' @inheritParams layer
#' @inheritParams geom_point
#' @export
#' @examples
#' # Generate data
#' huron <- data.frame(year = 1875:1972, level = as.vector(LakeHuron))
#' h <- ggplot(huron, aes(year))
#'
#' h + geom_ribbon(aes(ymin=0, ymax=level))
#' h + geom_area(aes(y = level))
#'
#' # Add aesthetic mappings
#' h +
#' geom_ribbon(aes(ymin = level - 1, ymax = level + 1), fill = "grey70") +
#' geom_line(aes(y = level))
geom_ribbon <- 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 = GeomRibbon,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
na.rm = na.rm,
...
)
)
}
#' @rdname animint2-gganimintproto
#' @format NULL
#' @usage NULL
#' @export
GeomRibbon <- gganimintproto("GeomRibbon", Geom,
default_aes = aes(colour = NA, fill = "grey20", size = 0.5, linetype = 1,
alpha = NA),
required_aes = c("x", "ymin", "ymax"),
draw_key = draw_key_polygon,
handle_na = function(data, params) {
data
},
draw_group = function(data, panel_scales, coord, na.rm = FALSE) {
if (na.rm) data <- data[stats::complete.cases(data[c("x", "ymin", "ymax")]), ]
data <- data[order(data$group, data$x), ]
# Check that aesthetics are constant
aes <- unique(data[c("colour", "fill", "size", "linetype", "alpha")])
if (nrow(aes) > 1) {
stop("Aesthetics can not vary with a ribbon")
}
aes <- as.list(aes)
# Instead of removing NA values from the data and plotting a single
# polygon, we want to "stop" plotting the polygon whenever we're
# missing values and "start" a new polygon as soon as we have new
# values. We do this by creating an id vector for polygonGrob that
# has distinct polygon numbers for sequences of non-NA values and NA
# for NA values in the original data. Example: c(NA, 2, 2, 2, NA, NA,
# 4, 4, 4, NA)
missing_pos <- !stats::complete.cases(data[c("x", "ymin", "ymax")])
ids <- cumsum(missing_pos) + 1
ids[missing_pos] <- NA
positions <- plyr::summarise(data,
x = c(x, rev(x)), y = c(ymax, rev(ymin)), id = c(ids, rev(ids)))
munched <- coord_munch(coord, positions, panel_scales)
ggname("geom_ribbon", polygonGrob(
munched$x, munched$y, id = munched$id,
default.units = "native",
gp = gpar(
fill = alpha(aes$fill, aes$alpha),
col = aes$colour,
lwd = aes$size * .pt,
lty = aes$linetype)
))
},
pre_process = function(g, g.data, ...) {
# Color set to match ggplot2 default of fill with no outside border.
if("fill"%in%names(g.data) & !"colour"%in%names(g.data)){
g.data[["colour"]] <- g.data[["fill"]]
}
return(list(g = g, g.data = g.data))
}
)
#' @rdname geom_ribbon
#' @export
geom_area <- function(mapping = NULL, data = NULL, stat = "identity",
position = "stack", na.rm = FALSE, show.legend = NA,
inherit.aes = TRUE, ...) {
layer(
data = data,
mapping = mapping,
stat = stat,
geom = GeomArea,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
na.rm = na.rm,
...
)
)
}
#' @rdname animint2-gganimintproto
#' @format NULL
#' @usage NULL
#' @export
GeomArea <- gganimintproto("GeomArea", GeomRibbon,
default_aes = aes(colour = NA, fill = "grey20", size = 0.5, linetype = 1,
alpha = NA),
required_aes = c("x", "y"),
setup_data = function(data, params) {
transform(data, ymin = 0, ymax = y)
},
pre_process = function(g, g.data, ...) {
g$geom <- "ribbon"
g.data <- g.data[order(g.data$x), ]
return(list(g = g, g.data = g.data))
}
)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.