6.2 Translating custom ggplot2 geoms

Version 2.0.0 of ggplot2 introduced a way for other R packages to implement custom geoms. Some great examples include: ggrepel, ggalt, ggraph, geomnet, ggmosaic and ggtern (Rudis 2016); (Pedersen 2016); (Tyner and Hofmann 2016); (Jeppson, Hofmann, and Cook 2016); (Hamilton 2016).19 Although the ggplotly() function translates most of the geoms bundled with the ggplot2 package, it has no way of knowing about the rendering rules for custom geoms. The plotly package does, however, provide 2 generic functions based on the S3 scheme that can leveraged to inform ggplotly() about these rules (Chambers 1992).20 To date, the ggmosaic and ggalt packages have taken advantage of this infrastructure to provide translations of their custom geoms to plotly.

In ggplot2, many geoms are special cases of other geoms. For example, geom_line() is equivalent to geom_path() once the data is sorted by the x variable. For cases like this, when a geom can be reduced to another lower-level (i.e., basic) geom, authors just have to write a method for the to_basic() generic function in plotly. In fact, within the package itself, the to_basic() function has a GeomLine method which simply sorts the data by the x variable then returns it with a class of GeomPath prefixed.

getS3method("to_basic", "GeomLine")
#> function (data, prestats_data, layout, params, p, ...) 
#> {
#>     data <- data[order(data[["x"]]), ]
#>     prefix_class(data, "GeomPath")
#> }
#> <environment: namespace:plotly>

If you have implemented a custom geom, say GeomCustom, rest assured that the data passed to to_basic() will be of class GeomCustom when ggplotly() is called on a plot with your geom. And assuming GeomCustom may be reduced to another lower-level geom support by plotly, a to_basic.GeomCustom() method that transforms the data into a form suitable for that lower-level geom is sufficient for adding support. Moreover, note that the data passed to to_basic() is essentially the last form of the data before the render stage and after statistics have been performed. This makes it trivial to add support for geoms like GeomXspline from the ggalt package.

# devtools::install_github("hrbrmstr/ggalt")
library(ggalt)
getS3method("to_basic", "GeomXspline")
#> function (data, prestats_data, layout, params, p, ...) 
#> {
#>     data <- data[order(data[["x"]]), ]
#>     prefix_class(data, "GeomPath")
#> }
#> <environment: namespace:plotly>

As shown in Figure 6.2, once the conversion has been provided. Users can call ggplotly() on the ggplot object containing the custom geom just like any other ggplot object.

# example from `help(geom_xspline)`
set.seed(1492)
dat <- data.frame(
  x = c(1:10, 1:10, 1:10),
  y = c(sample(15:30, 10), 2 * sample(15:30, 10), 3 * sample(15:30, 10)),
  group = factor(c(rep(1, 10), rep(2, 10), rep(3, 10)))
)
p <- ggplot(dat, aes(x, y, group = group, color = factor(group))) +
  geom_point(color = "black") +
  geom_smooth(se = FALSE, linetype = "dashed", size = 0.5) +
  geom_xspline(spline_shape = 1, size = 0.5)
ggplotly(p) %>% hide_legend()

Figure 6.2: Converting GeomXspline from the ggalt package to plotly.js via ggplotly().

In more complicated cases, where your custom geom can not be converted to a lower level geom, a custom method for the geom2trace() generic is required (methods(geom2trace) lists all the basic geoms that we natively support). This method should involve a conversion from a data frame to a list-like object conforming to the plotly.js figure reference.

References

Rudis, Bob. 2016. Ggalt: Extra Coordinate Systems, Geoms and Statistical Transformations for ’Ggplot2’. https://CRAN.R-project.org/package=ggalt.

Pedersen, Thomas Lin. 2016. Ggraph: An Implementation of Grammar of Graphics for Graphs and Networks.

Tyner, Samantha, and Heike Hofmann. 2016. Geomnet: Network Visualization in the ’Ggplot2’ Framework. https://CRAN.R-project.org/package=geomnet.

Jeppson, Haley, Heike Hofmann, and Di Cook. 2016. Ggmosaic: Mosaic Plots in the ’Ggplot2’ Framework. http://github.com/haleyjeppson/ggmosaic.

Hamilton, Nicholas. 2016. Ggtern: An Extension to ’Ggplot2’, for the Creation of Ternary Diagrams. https://CRAN.R-project.org/package=ggtern.

Chambers, J. M. 1992. “Classes and Methods: Object-Oriented Programming in S.” In Statistical Models in S, edited by J. M. Chambers and T. J. Hastie. Wadsworth & Brooks/Cole.


  1. There are many other useful extension packages that are listed on this website – https://www.ggplot2-exts.org

  2. For those new to S3, http://adv-r.had.co.nz/S3.html provides an approachable introduction and overview (Wickham 2014).