20.4 Geoms

Why making a new geom_?

  • not meaningful data by any current geoms
  • combination of the output of multiple geoms
  • needs for grobs not currently available from existing geoms.

The logic of a geom is made of subsequent calls:

Implementation is easier for draw_group()

  • setup_params()+setup_data()
  • overwriting the setup_data()

Example Reparameterisation of geom_segment() with geom_spoke()

print(GeomSpoke$setup_data)
<ggproto method>
  <Wrapper function>
    function (...) 
setup_data(...)

  <Inner function (f)>
    function (data, params) 
{
    data$radius <- data$radius %||% params$radius
    data$angle <- data$angle %||% params$angle
    transform(data, xend = x + cos(angle) * radius, yend = y + 
        sin(angle) * radius)
}

Example geom_smooth() as a combination of geom_line() and geom_ribbon()

  • preparing the data for each of the geoms inside the draw_*()
print(GeomSmooth$draw_group)
<ggproto method>
  <Wrapper function>
    function (...) 
draw_group(...)

  <Inner function (f)>
    function (data, panel_params, coord, lineend = "butt", linejoin = "round", 
    linemitre = 10, se = FALSE, flipped_aes = FALSE) 
{
    ribbon <- transform(data, colour = NA)
    path <- transform(data, alpha = NA)
    ymin = flipped_names(flipped_aes)$ymin
    ymax = flipped_names(flipped_aes)$ymax
    has_ribbon <- se && !is.null(data[[ymax]]) && !is.null(data[[ymin]])
    gList(if (has_ribbon) 
        GeomRibbon$draw_group(ribbon, panel_params, coord, flipped_aes = flipped_aes), 
        GeomLine$draw_panel(path, panel_params, coord, lineend = lineend, 
            linejoin = linejoin, linemitre = linemitre))
}