From b9b9fbdeaacda8726570ef6faa05082a87d9bd84 Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Fri, 10 Aug 2018 09:44:41 -0400 Subject: [PATCH 01/11] rename range() function of coord to backtransform_range() --- NEWS.md | 5 +++++ R/coord-.r | 17 ++++++++++++++--- R/coord-cartesian-.r | 2 +- R/coord-flip.r | 2 +- R/coord-map.r | 2 +- R/coord-munch.r | 2 +- R/coord-polar.r | 2 +- R/coord-transform.r | 2 +- R/geom-abline.r | 2 +- R/geom-hline.r | 2 +- R/geom-vline.r | 2 +- R/sf.R | 2 +- R/summarise-plot.R | 2 +- man/ggplot2-ggproto.Rd | 5 +++-- 14 files changed, 33 insertions(+), 16 deletions(-) diff --git a/NEWS.md b/NEWS.md index 4312b972e7..85da979140 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,6 +10,11 @@ * `coord_sf()` now accepts two new parameters, `label_graticule` and `label_axes`, that can be used to specify which graticules to label on which side of the plot (@clauswilke, #2846). + +* The function `range()` in `Coord` has been renamed to `backtransform_range()` + to clarify its intended meaning. This affects developers of custom coords. It + may also affect developers of custom geoms that use the `range()` function. That + code should be migrated to use `backtransform_range()` (@clauswilke, breaking change). * `geom_sf()` now respects `lineend`, `linejoin`, and `linemitre` parameters for lines and polygons (@alistaire47, #2826) diff --git a/R/coord-.r b/R/coord-.r index 541cd827d9..302c5e6995 100644 --- a/R/coord-.r +++ b/R/coord-.r @@ -13,12 +13,13 @@ #' - `render_bg`: Renders background elements. #' - `render_axis_h`: Renders the horizontal axes. #' - `render_axis_v`: Renders the vertical axes. -#' - `range(panel_params)`: Extracts the panel range provided +#' - `backtransform_range(panel_params)`: Extracts the panel range provided #' in `panel_params` (created by `setup_panel_params()`, see below) and -#' back-transforms to data coordinates. This back-transformation is needed +#' backtransforms to data coordinates. This back-transformation is needed #' for coords such as `coord_flip()`, `coord_polar()`, `coord_trans()` where #' the range in the transformed coordinates differs from the range in the #' untransformed coordinates. +#' - `range`: Deprecated, do not implement. Calls `backtransform_range()`. #' - `transform`: Transforms x and y coordinates. #' - `distance`: Calculates distance. #' - `is_linear`: Returns `TRUE` if the coordinate system is @@ -84,7 +85,7 @@ Coord <- ggproto("Coord", # transform range given in transformed coordinates # back into range in given in (possibly scale-transformed) # data coordinates - range = function(panel_params) { + backtransform_range = function(panel_params) { warning( "range backtransformation not implemented in this coord; plot may be wrong.", call. = FALSE @@ -92,6 +93,16 @@ Coord <- ggproto("Coord", list(x = panel_params$x.range, y = panel_params$y.range) }, + # deprecated, do not use or reimplement + # kept only for backwards compatibility + range = function(self, panel_params) { + warning( + "function `Coord$range()` is deprecated; use `Coord$backtransform_range()`.", + call. = FALSE + ) + self$backtransform_range(panel_params) + }, + setup_panel_params = function(scale_x, scale_y, params = list()) { list() }, diff --git a/R/coord-cartesian-.r b/R/coord-cartesian-.r index b162b6359f..6ff7b6239e 100644 --- a/R/coord-cartesian-.r +++ b/R/coord-cartesian-.r @@ -83,7 +83,7 @@ CoordCartesian <- ggproto("CoordCartesian", Coord, dist_euclidean(x, y) / max_dist }, - range = function(panel_params) { + backtransform_range = function(panel_params) { list(x = panel_params$x.range, y = panel_params$y.range) }, diff --git a/R/coord-flip.r b/R/coord-flip.r index c3637a6ddb..c25de67924 100644 --- a/R/coord-flip.r +++ b/R/coord-flip.r @@ -44,7 +44,7 @@ CoordFlip <- ggproto("CoordFlip", CoordCartesian, CoordCartesian$transform(data, panel_params) }, - range = function(panel_params) { + backtransform_range = function(panel_params) { list(x = panel_params$y.range, y = panel_params$x.range) }, diff --git a/R/coord-map.r b/R/coord-map.r index a08d8a8e16..de16ca84fb 100644 --- a/R/coord-map.r +++ b/R/coord-map.r @@ -119,7 +119,7 @@ CoordMap <- ggproto("CoordMap", Coord, out }, - range = function(panel_params) { + backtransform_range = function(panel_params) { # range is stored in data coordinates and doesn't have to be back-transformed list(x = panel_params$x.range, y = panel_params$y.range) }, diff --git a/R/coord-munch.r b/R/coord-munch.r index b39d5afb26..c968bea6e2 100644 --- a/R/coord-munch.r +++ b/R/coord-munch.r @@ -15,7 +15,7 @@ coord_munch <- function(coord, data, range, segment_length = 0.01) { if (coord$is_linear()) return(coord$transform(data, range)) # range has theta and r values; get corresponding x and y values - ranges <- coord$range(range) + ranges <- coord$backtransform_range(range) # Convert any infinite locations into max/min # Only need to work with x and y because for munching, those are the diff --git a/R/coord-polar.r b/R/coord-polar.r index cbf496686d..2318595328 100644 --- a/R/coord-polar.r +++ b/R/coord-polar.r @@ -90,7 +90,7 @@ CoordPolar <- ggproto("CoordPolar", Coord, dist_polar(r, theta) }, - range = function(self, panel_params) { + backtransform_range = function(self, panel_params) { setNames( list(panel_params$theta.range, panel_params$r.range), c(self$theta, self$r) diff --git a/R/coord-transform.r b/R/coord-transform.r index efe04b167c..798b2e5cac 100644 --- a/R/coord-transform.r +++ b/R/coord-transform.r @@ -119,7 +119,7 @@ CoordTrans <- ggproto("CoordTrans", Coord, dist_euclidean(self$trans$x$transform(x), self$trans$y$transform(y)) / max_dist }, - range = function(self, panel_params) { + backtransform_range = function(self, panel_params) { list( x = self$trans$x$inverse(panel_params$x.range), y = self$trans$y$inverse(panel_params$y.range) diff --git a/R/geom-abline.r b/R/geom-abline.r index 96c5565add..1d5b88fc63 100644 --- a/R/geom-abline.r +++ b/R/geom-abline.r @@ -111,7 +111,7 @@ geom_abline <- function(mapping = NULL, data = NULL, #' @export GeomAbline <- ggproto("GeomAbline", Geom, draw_panel = function(data, panel_params, coord) { - ranges <- coord$range(panel_params) + ranges <- coord$backtransform_range(panel_params) data$x <- ranges$x[1] data$xend <- ranges$x[2] diff --git a/R/geom-hline.r b/R/geom-hline.r index 6b3438aaf0..a067c5b77c 100644 --- a/R/geom-hline.r +++ b/R/geom-hline.r @@ -37,7 +37,7 @@ geom_hline <- function(mapping = NULL, data = NULL, #' @export GeomHline <- ggproto("GeomHline", Geom, draw_panel = function(data, panel_params, coord) { - ranges <- coord$range(panel_params) + ranges <- coord$backtransform_range(panel_params) data$x <- ranges$x[1] data$xend <- ranges$x[2] diff --git a/R/geom-vline.r b/R/geom-vline.r index b2e29f9bdc..1b6668976d 100644 --- a/R/geom-vline.r +++ b/R/geom-vline.r @@ -37,7 +37,7 @@ geom_vline <- function(mapping = NULL, data = NULL, #' @export GeomVline <- ggproto("GeomVline", Geom, draw_panel = function(data, panel_params, coord) { - ranges <- coord$range(panel_params) + ranges <- coord$backtransform_range(panel_params) data$x <- data$xintercept data$xend <- data$xintercept diff --git a/R/sf.R b/R/sf.R index 9d99dfce23..0a89b3ef08 100644 --- a/R/sf.R +++ b/R/sf.R @@ -543,7 +543,7 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, ) }, - range = function(panel_params) { + backtransform_range = function(panel_params) { list(x = panel_params$x_range, y = panel_params$y_range) }, diff --git a/R/summarise-plot.R b/R/summarise-plot.R index 4906ac10b7..21bef7d1ca 100644 --- a/R/summarise-plot.R +++ b/R/summarise-plot.R @@ -38,7 +38,7 @@ summarise_layout = function(p) { setNames(res, facet_vars) }) - xyranges <- lapply(l$panel_params, l$coord$range) + xyranges <- lapply(l$panel_params, l$coord$backtransform_range) layout$xmin <- vapply(xyranges, function(xyrange) xyrange$x[[1]], numeric(1)) layout$xmax <- vapply(xyranges, function(xyrange) xyrange$x[[2]], numeric(1)) layout$ymin <- vapply(xyranges, function(xyrange) xyrange$y[[1]], numeric(1)) diff --git a/man/ggplot2-ggproto.Rd b/man/ggplot2-ggproto.Rd index 32c3fe5cfc..f8d6d0244b 100644 --- a/man/ggplot2-ggproto.Rd +++ b/man/ggplot2-ggproto.Rd @@ -201,12 +201,13 @@ object, you typically will want to implement one or more of the following: \item \code{render_bg}: Renders background elements. \item \code{render_axis_h}: Renders the horizontal axes. \item \code{render_axis_v}: Renders the vertical axes. -\item \code{range(panel_params)}: Extracts the panel range provided +\item \code{backtransform_range(panel_params)}: Extracts the panel range provided in \code{panel_params} (created by \code{setup_panel_params()}, see below) and -back-transforms to data coordinates. This back-transformation is needed +backtransforms to data coordinates. This back-transformation is needed for coords such as \code{coord_flip()}, \code{coord_polar()}, \code{coord_trans()} where the range in the transformed coordinates differs from the range in the untransformed coordinates. +\item \code{range}: Deprecated, do not implement. Calls \code{backtransform_range()}. \item \code{transform}: Transforms x and y coordinates. \item \code{distance}: Calculates distance. \item \code{is_linear}: Returns \code{TRUE} if the coordinate system is From 9b990b2bea7156f270251626fab9c45e53374df6 Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Thu, 23 Aug 2018 14:56:03 -0500 Subject: [PATCH 02/11] fix typo --- R/coord-.r | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/coord-.r b/R/coord-.r index 302c5e6995..77663e0516 100644 --- a/R/coord-.r +++ b/R/coord-.r @@ -15,7 +15,7 @@ #' - `render_axis_v`: Renders the vertical axes. #' - `backtransform_range(panel_params)`: Extracts the panel range provided #' in `panel_params` (created by `setup_panel_params()`, see below) and -#' backtransforms to data coordinates. This back-transformation is needed +#' back-transforms to data coordinates. This back-transformation is needed #' for coords such as `coord_flip()`, `coord_polar()`, `coord_trans()` where #' the range in the transformed coordinates differs from the range in the #' untransformed coordinates. From d4be2f115dd6f9484c644f6e027cd3f77233c25f Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Mon, 17 Sep 2018 19:09:22 -0500 Subject: [PATCH 03/11] Add range function to Coord(). --- NEWS.md | 9 +++++---- R/coord-.r | 16 +++++++++------- R/coord-cartesian-.r | 4 ++++ R/coord-map.r | 5 +++++ R/coord-polar.r | 6 ++++++ R/sf.R | 6 ++++++ R/summarise-plot.R | 2 +- man/ggplot2-ggproto.Rd | 7 +++++-- man/ggsf.Rd | 2 +- 9 files changed, 42 insertions(+), 15 deletions(-) diff --git a/NEWS.md b/NEWS.md index 85da979140..114bbca213 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,10 +11,11 @@ that can be used to specify which graticules to label on which side of the plot (@clauswilke, #2846). -* The function `range()` in `Coord` has been renamed to `backtransform_range()` - to clarify its intended meaning. This affects developers of custom coords. It - may also affect developers of custom geoms that use the `range()` function. That - code should be migrated to use `backtransform_range()` (@clauswilke, breaking change). +* `Coord` objects now have a function `backtransform_range()` that returns the + panel range in data coordinates. This change may affect developers of custom coords. It + may also affect developers of custom geoms that use the `range()` function. In + some applications, `backtransform_range()` may be more appropriate. + (@clauswilke, #2821). * `geom_sf()` now respects `lineend`, `linejoin`, and `linemitre` parameters for lines and polygons (@alistaire47, #2826) diff --git a/R/coord-.r b/R/coord-.r index 77663e0516..1d9977c192 100644 --- a/R/coord-.r +++ b/R/coord-.r @@ -19,7 +19,10 @@ #' for coords such as `coord_flip()`, `coord_polar()`, `coord_trans()` where #' the range in the transformed coordinates differs from the range in the #' untransformed coordinates. -#' - `range`: Deprecated, do not implement. Calls `backtransform_range()`. +#' - `range(panel_params)`: Extracts the panel range provided +#' in `panel_params` (created by `setup_panel_params()`, see below) and +#' returns it. Unlike `backtransform_range()`, this function does not perform +#' any back-transformation and instead returns final transformed coordinates. #' - `transform`: Transforms x and y coordinates. #' - `distance`: Calculates distance. #' - `is_linear`: Returns `TRUE` if the coordinate system is @@ -87,20 +90,19 @@ Coord <- ggproto("Coord", # data coordinates backtransform_range = function(panel_params) { warning( - "range backtransformation not implemented in this coord; plot may be wrong.", + "range backtransformation not implemented in this coord; results may be wrong.", call. = FALSE ) list(x = panel_params$x.range, y = panel_params$y.range) }, - # deprecated, do not use or reimplement - # kept only for backwards compatibility - range = function(self, panel_params) { + # return range stored in panel_params + range = function(panel_params) { warning( - "function `Coord$range()` is deprecated; use `Coord$backtransform_range()`.", + "range calculation not implemented in this coord; results may be wrong.", call. = FALSE ) - self$backtransform_range(panel_params) + list(x = panel_params$x.range, y = panel_params$y.range) }, setup_panel_params = function(scale_x, scale_y, params = list()) { diff --git a/R/coord-cartesian-.r b/R/coord-cartesian-.r index 6ff7b6239e..24424ba531 100644 --- a/R/coord-cartesian-.r +++ b/R/coord-cartesian-.r @@ -83,6 +83,10 @@ CoordCartesian <- ggproto("CoordCartesian", Coord, dist_euclidean(x, y) / max_dist }, + range = function(panel_params) { + list(x = panel_params$x.range, y = panel_params$y.range) + }, + backtransform_range = function(panel_params) { list(x = panel_params$x.range, y = panel_params$y.range) }, diff --git a/R/coord-map.r b/R/coord-map.r index de16ca84fb..50fbb00d07 100644 --- a/R/coord-map.r +++ b/R/coord-map.r @@ -124,6 +124,11 @@ CoordMap <- ggproto("CoordMap", Coord, list(x = panel_params$x.range, y = panel_params$y.range) }, + # not sure yet how to implement this, panel params store backtransformed range + #range = function(panel_params) { + # list(x = panel_params$x.range, y = panel_params$y.range) + #}, + distance = function(x, y, panel_params) { max_dist <- dist_central_angle(panel_params$x.range, panel_params$y.range) dist_central_angle(x, y) / max_dist diff --git a/R/coord-polar.r b/R/coord-polar.r index 2318595328..4b610a010b 100644 --- a/R/coord-polar.r +++ b/R/coord-polar.r @@ -97,6 +97,12 @@ CoordPolar <- ggproto("CoordPolar", Coord, ) }, + range = function(self, panel_params) { + # return angle as x and radius as y + # downstream functions (e.g. summarise_layout()) expect x and y + list(x = panel_params$theta.range, y = panel_params$r.range) + }, + setup_panel_params = function(self, scale_x, scale_y, params = list()) { ret <- list(x = list(), y = list()) diff --git a/R/sf.R b/R/sf.R index 0a89b3ef08..2e19ff58ae 100644 --- a/R/sf.R +++ b/R/sf.R @@ -544,9 +544,15 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, }, backtransform_range = function(panel_params) { + # this does not actually return backtransformed ranges in the general case, needs fixing list(x = panel_params$x_range, y = panel_params$y_range) }, + range = function(panel_params) { + list(x = panel_params$x_range, y = panel_params$y_range) + }, + + # CoordSf enforces a fixed aspect ratio -> axes cannot be changed freely under faceting is_free = function() FALSE, diff --git a/R/summarise-plot.R b/R/summarise-plot.R index 21bef7d1ca..4906ac10b7 100644 --- a/R/summarise-plot.R +++ b/R/summarise-plot.R @@ -38,7 +38,7 @@ summarise_layout = function(p) { setNames(res, facet_vars) }) - xyranges <- lapply(l$panel_params, l$coord$backtransform_range) + xyranges <- lapply(l$panel_params, l$coord$range) layout$xmin <- vapply(xyranges, function(xyrange) xyrange$x[[1]], numeric(1)) layout$xmax <- vapply(xyranges, function(xyrange) xyrange$x[[2]], numeric(1)) layout$ymin <- vapply(xyranges, function(xyrange) xyrange$y[[1]], numeric(1)) diff --git a/man/ggplot2-ggproto.Rd b/man/ggplot2-ggproto.Rd index f8d6d0244b..d38cc82b35 100644 --- a/man/ggplot2-ggproto.Rd +++ b/man/ggplot2-ggproto.Rd @@ -203,11 +203,14 @@ object, you typically will want to implement one or more of the following: \item \code{render_axis_v}: Renders the vertical axes. \item \code{backtransform_range(panel_params)}: Extracts the panel range provided in \code{panel_params} (created by \code{setup_panel_params()}, see below) and -backtransforms to data coordinates. This back-transformation is needed +back-transforms to data coordinates. This back-transformation is needed for coords such as \code{coord_flip()}, \code{coord_polar()}, \code{coord_trans()} where the range in the transformed coordinates differs from the range in the untransformed coordinates. -\item \code{range}: Deprecated, do not implement. Calls \code{backtransform_range()}. +\item \code{range(panel_params)}: Extracts the panel range provided +in \code{panel_params} (created by \code{setup_panel_params()}, see below) and +returns it. Unlike \code{backtransform_range()}, this function does not perform +any back-transformation and instead returns final transformed coordinates. \item \code{transform}: Transforms x and y coordinates. \item \code{distance}: Calculates distance. \item \code{is_linear}: Returns \code{TRUE} if the coordinate system is diff --git a/man/ggsf.Rd b/man/ggsf.Rd index 56b2e691ea..e842b6bb5e 100644 --- a/man/ggsf.Rd +++ b/man/ggsf.Rd @@ -140,7 +140,7 @@ which side of the plot. Meridians are indicated by \code{"E"} (for East) and parallels by \code{"N"} (for North). Default is \code{"--EN"}, which specifies (clockwise from the top) no labels on the top, none on the right, meridians on the bottom, and parallels on the left. Alternatively, this setting could have been -specified with \code{list(left = "N", bottom = "E")}. +specified with \code{list(bottom = "E", left = "N")}. This parameter can be used alone or in combination with \code{label_graticule}.} From 8d6c6896faf596a9f19c04bd686910ced89efa00 Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Mon, 17 Sep 2018 19:13:29 -0500 Subject: [PATCH 04/11] add range() to coord_trans() --- R/coord-transform.r | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/R/coord-transform.r b/R/coord-transform.r index 798b2e5cac..237c9dbe1f 100644 --- a/R/coord-transform.r +++ b/R/coord-transform.r @@ -126,6 +126,13 @@ CoordTrans <- ggproto("CoordTrans", Coord, ) }, + range = function(self, panel_params) { + list( + x = panel_params$x.range, + y = panel_params$y.range + ) + }, + transform = function(self, data, panel_params) { trans_x <- function(data) transform_value(self$trans$x, data, panel_params$x.range) trans_y <- function(data) transform_value(self$trans$y, data, panel_params$y.range) From 26d471f20be0907ccb3e30fd140dae9475622fb4 Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Mon, 17 Sep 2018 19:16:46 -0500 Subject: [PATCH 05/11] add warnings --- R/coord-map.r | 10 +++++++--- R/sf.R | 4 ++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/R/coord-map.r b/R/coord-map.r index 50fbb00d07..d11bbf7d79 100644 --- a/R/coord-map.r +++ b/R/coord-map.r @@ -125,9 +125,13 @@ CoordMap <- ggproto("CoordMap", Coord, }, # not sure yet how to implement this, panel params store backtransformed range - #range = function(panel_params) { - # list(x = panel_params$x.range, y = panel_params$y.range) - #}, + range = function(panel_params) { + warning( + "range calculation in transformed coordinates not implemented in this coord; results may be wrong.", + call. = FALSE + ) + list(x = panel_params$x.range, y = panel_params$y.range) + }, distance = function(x, y, panel_params) { max_dist <- dist_central_angle(panel_params$x.range, panel_params$y.range) diff --git a/R/sf.R b/R/sf.R index 2e19ff58ae..e51777e7d8 100644 --- a/R/sf.R +++ b/R/sf.R @@ -545,6 +545,10 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, backtransform_range = function(panel_params) { # this does not actually return backtransformed ranges in the general case, needs fixing + warning( + "range backtransformation not implemented in this coord; results may be wrong.", + call. = FALSE + ) list(x = panel_params$x_range, y = panel_params$y_range) }, From a1971244fefd92a0857ac26b5a650a01da00a29d Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Mon, 17 Sep 2018 21:54:07 -0500 Subject: [PATCH 06/11] fix range functions for coord_flip() and coord_polar() --- R/coord-flip.r | 6 ++++++ R/coord-polar.r | 9 ++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/R/coord-flip.r b/R/coord-flip.r index c25de67924..0569297cee 100644 --- a/R/coord-flip.r +++ b/R/coord-flip.r @@ -48,6 +48,12 @@ CoordFlip <- ggproto("CoordFlip", CoordCartesian, list(x = panel_params$y.range, y = panel_params$x.range) }, + range = function(panel_params) { + # summarise_layout() expects the original x and y ranges here, + # not the ones we would get after flipping the axes + list(x = panel_params$y.range, y = panel_params$x.range) + }, + setup_panel_params = function(self, scale_x, scale_y, params = list()) { parent <- ggproto_parent(CoordCartesian, self) panel_params <- parent$setup_panel_params(scale_x, scale_y, params) diff --git a/R/coord-polar.r b/R/coord-polar.r index 4b610a010b..6ae91abdaf 100644 --- a/R/coord-polar.r +++ b/R/coord-polar.r @@ -98,9 +98,12 @@ CoordPolar <- ggproto("CoordPolar", Coord, }, range = function(self, panel_params) { - # return angle as x and radius as y - # downstream functions (e.g. summarise_layout()) expect x and y - list(x = panel_params$theta.range, y = panel_params$r.range) + # summarise_layout() expects that the x and y ranges here + # match the setting from self$theta and self$r + setNames( + list(panel_params$theta.range, panel_params$r.range), + c(self$theta, self$r) + ) }, setup_panel_params = function(self, scale_x, scale_y, params = list()) { From 6d9cf966d7170a7ecb02f8f1b94dcc5d903fbb14 Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Mon, 17 Sep 2018 22:56:49 -0500 Subject: [PATCH 07/11] Expand documentation for summarise_layout(). Closes #2895. --- R/summarise-plot.R | 39 ++++++++++++++++++++++++++++++++++++ man/summarise_plot.Rd | 46 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/R/summarise-plot.R b/R/summarise-plot.R index 4906ac10b7..3ffa9997c6 100644 --- a/R/summarise-plot.R +++ b/R/summarise-plot.R @@ -2,6 +2,45 @@ #' #' These functions provide summarised information about built ggplot objects. #' +#' There are three types of summary that can be obtained: A summary of the plot layout, +#' a summary of the plot coord, and a summary of plot layers. +#' +#' @section Layout summary: +#' +#' The function `summarise_layout()` returns a table that provides information about +#' the plot panel(s) in the built plot. The table has the following columns: +#' +#' \describe{ +#' \item{`panel`}{A factor indicating the individual plot panels.} +#' \item{`row`}{Row number in the grid of panels.} +#' \item{`col`}{Column number in the grid of panels.} +#' \item{`vars`}{A list of lists. For each panel, the respective list +#' provides the variables and their values that specify the panel.} +#' \item{`xmin`, `xmax`}{The minimum and maximum values of the variable mapped to +#' the x aesthetic, in transformed coordinates.} +#' \item{`ymin`, `ymax`}{The minimum and maximum values of the variable mapped to +#' the y aesthetic, in transformed coordinates.} +#' \item{`xscale`}{The scale object applied to the x aesthetic.} +#' \item{`yscale`}{The scale object applied to the y aesthetic.} +#' } +#' +#' Importantly, the values for `xmin`, `xmax`, `ymin`, `ymax`, `xscale`, and `yscale` +#' are determined by the variables that are mapped to `x` and `y` in the `aes()` call. +#' So even if a coord changes how x and y are shown in the final plot (as is the case +#' for `coord_flip()` or `coord_polar()`), these changes have no effect on the results +#' returned by `summarise_plot()`. +#' +#' @section Coord summary: +#' +#' The function `summarise_coord()` returns information about the log base for +#' coordinates that are log-transformed in `coord_trans()`, and it also indicates +#' whether the coord has flipped the x and y axes. +#' +#' @section Layer summary: +#' +#' The function `summarise_layers()` returns a table with a single column, `mapping`, which +#' contains information about aesthetic mapping for each layer. +#' #' @param p A ggplot_built object. #' #' @examples diff --git a/man/summarise_plot.Rd b/man/summarise_plot.Rd index 2273619e21..8c05cd57d2 100644 --- a/man/summarise_plot.Rd +++ b/man/summarise_plot.Rd @@ -19,6 +19,52 @@ summarise_layers(p) \description{ These functions provide summarised information about built ggplot objects. } +\details{ +There are three types of summary that can be obtained: A summary of the plot layout, +a summary of the plot coord, and a summary of plot layers. +} +\section{Layout summary}{ + + +The function \code{summarise_layout()} returns a table that provides information about +the plot panel(s) in the built plot. The table has the following columns: + +\describe{ +\item{\code{panel}}{A factor indicating the individual plot panels.} +\item{\code{row}}{Row number in the grid of panels.} +\item{\code{col}}{Column number in the grid of panels.} +\item{\code{vars}}{A list of lists. For each panel, the respective list +provides the variables and their values that specify the panel.} +\item{\code{xmin}, \code{xmax}}{The minimum and maximum values of the variable mapped to +the x aesthetic, in transformed coordinates.} +\item{\code{ymin}, \code{ymax}}{The minimum and maximum values of the variable mapped to +the y aesthetic, in transformed coordinates.} +\item{\code{xscale}}{The scale object applied to the x aesthetic.} +\item{\code{yscale}}{The scale object applied to the y aesthetic.} +} + +Importantly, the values for \code{xmin}, \code{xmax}, \code{ymin}, \code{ymax}, \code{xscale}, and \code{yscale} +are determined by the variables that are mapped to \code{x} and \code{y} in the \code{aes()} call. +So even if a coord changes how x and y are shown in the final plot (as is the case +for \code{coord_flip()} or \code{coord_polar()}), these changes have no effect on the results +returned by \code{summarise_plot()}. +} + +\section{Coord summary}{ + + +The function \code{summarise_coord()} returns information about the log base for +coordinates that are log-transformed in \code{coord_trans()}, and it also indicates +whether the coord has flipped the x and y axes. +} + +\section{Layer summary}{ + + +The function \code{summarise_layers()} returns a table with a single column, \code{mapping}, which +contains information about aesthetic mapping for each layer. +} + \examples{ p <- ggplot(mpg, aes(displ, hwy)) + geom_point() + facet_wrap(~class) b <- ggplot_build(p) From 380d81103363ae8d81e9b5f029a1a522b6f5977b Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Tue, 18 Sep 2018 00:11:49 -0500 Subject: [PATCH 08/11] improve back-compatibility --- R/coord-.r | 21 ++++++++++++++------- R/coord-flip.r | 2 +- R/coord-map.r | 9 ++++----- R/coord-polar.r | 5 +---- man/ggplot2-ggproto.Rd | 15 ++++++++++----- 5 files changed, 30 insertions(+), 22 deletions(-) diff --git a/R/coord-.r b/R/coord-.r index 1d9977c192..9c84903c65 100644 --- a/R/coord-.r +++ b/R/coord-.r @@ -15,14 +15,19 @@ #' - `render_axis_v`: Renders the vertical axes. #' - `backtransform_range(panel_params)`: Extracts the panel range provided #' in `panel_params` (created by `setup_panel_params()`, see below) and -#' back-transforms to data coordinates. This back-transformation is needed -#' for coords such as `coord_flip()`, `coord_polar()`, `coord_trans()` where -#' the range in the transformed coordinates differs from the range in the -#' untransformed coordinates. +#' back-transforms to data coordinates. This back-transformation can be needed +#' for coords such as `coord_trans()` where the range in the transformed +#' coordinates differs from the range in the untransformed coordinates. Returns +#' a list of two ranges, `x` and `y`, and these correspond to the variables +#' mapped to the `x` and `y` aesthetics, even for coords such as `coord_flip()` +#' where the `x` aesthetic is shown along the y direction and vice versa. #' - `range(panel_params)`: Extracts the panel range provided #' in `panel_params` (created by `setup_panel_params()`, see below) and #' returns it. Unlike `backtransform_range()`, this function does not perform -#' any back-transformation and instead returns final transformed coordinates. +#' any back-transformation and instead returns final transformed coordinates. Returns +#' a list of two ranges, `x` and `y`, and these correspond to the variables +#' mapped to the `x` and `y` aesthetics, even for coords such as `coord_flip()` +#' where the `x` aesthetic is shown along the y direction and vice versa. #' - `transform`: Transforms x and y coordinates. #' - `distance`: Calculates distance. #' - `is_linear`: Returns `TRUE` if the coordinate system is @@ -88,12 +93,14 @@ Coord <- ggproto("Coord", # transform range given in transformed coordinates # back into range in given in (possibly scale-transformed) # data coordinates - backtransform_range = function(panel_params) { + backtransform_range = function(self, panel_params) { warning( "range backtransformation not implemented in this coord; results may be wrong.", call. = FALSE ) - list(x = panel_params$x.range, y = panel_params$y.range) + # return result from range function for backwards compatibility + # before ggplot2 3.0.1 + self$range(panel_params) }, # return range stored in panel_params diff --git a/R/coord-flip.r b/R/coord-flip.r index 0569297cee..ca85d5ce48 100644 --- a/R/coord-flip.r +++ b/R/coord-flip.r @@ -45,7 +45,7 @@ CoordFlip <- ggproto("CoordFlip", CoordCartesian, }, backtransform_range = function(panel_params) { - list(x = panel_params$y.range, y = panel_params$x.range) + self$range(panel_params) }, range = function(panel_params) { diff --git a/R/coord-map.r b/R/coord-map.r index d11bbf7d79..69ca8d7593 100644 --- a/R/coord-map.r +++ b/R/coord-map.r @@ -124,12 +124,11 @@ CoordMap <- ggproto("CoordMap", Coord, list(x = panel_params$x.range, y = panel_params$y.range) }, - # not sure yet how to implement this, panel params store backtransformed range range = function(panel_params) { - warning( - "range calculation in transformed coordinates not implemented in this coord; results may be wrong.", - call. = FALSE - ) + # Range in projected coordinates: + # list(x = panel_params$x.proj, y = panel_params$y.proj) + # However, coord_map() does never really work with transformed coordinates, + # so return unprojected data coordinates here list(x = panel_params$x.range, y = panel_params$y.range) }, diff --git a/R/coord-polar.r b/R/coord-polar.r index 6ae91abdaf..0169990750 100644 --- a/R/coord-polar.r +++ b/R/coord-polar.r @@ -91,10 +91,7 @@ CoordPolar <- ggproto("CoordPolar", Coord, }, backtransform_range = function(self, panel_params) { - setNames( - list(panel_params$theta.range, panel_params$r.range), - c(self$theta, self$r) - ) + self$range(panel_params) }, range = function(self, panel_params) { diff --git a/man/ggplot2-ggproto.Rd b/man/ggplot2-ggproto.Rd index d38cc82b35..bad0d955d7 100644 --- a/man/ggplot2-ggproto.Rd +++ b/man/ggplot2-ggproto.Rd @@ -203,14 +203,19 @@ object, you typically will want to implement one or more of the following: \item \code{render_axis_v}: Renders the vertical axes. \item \code{backtransform_range(panel_params)}: Extracts the panel range provided in \code{panel_params} (created by \code{setup_panel_params()}, see below) and -back-transforms to data coordinates. This back-transformation is needed -for coords such as \code{coord_flip()}, \code{coord_polar()}, \code{coord_trans()} where -the range in the transformed coordinates differs from the range in the -untransformed coordinates. +back-transforms to data coordinates. This back-transformation can be needed +for coords such as \code{coord_trans()} where the range in the transformed +coordinates differs from the range in the untransformed coordinates. Returns +a list of two ranges, \code{x} and \code{y}, and these correspond to the variables +mapped to the \code{x} and \code{y} aesthetics, even for coords such as \code{coord_flip()} +where the \code{x} aesthetic is shown along the y direction and vice versa. \item \code{range(panel_params)}: Extracts the panel range provided in \code{panel_params} (created by \code{setup_panel_params()}, see below) and returns it. Unlike \code{backtransform_range()}, this function does not perform -any back-transformation and instead returns final transformed coordinates. +any back-transformation and instead returns final transformed coordinates. Returns +a list of two ranges, \code{x} and \code{y}, and these correspond to the variables +mapped to the \code{x} and \code{y} aesthetics, even for coords such as \code{coord_flip()} +where the \code{x} aesthetic is shown along the y direction and vice versa. \item \code{transform}: Transforms x and y coordinates. \item \code{distance}: Calculates distance. \item \code{is_linear}: Returns \code{TRUE} if the coordinate system is From dab7e81143aeeae3d74b5a1887d6b0b9ce8aea12 Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Tue, 18 Sep 2018 13:43:58 -0500 Subject: [PATCH 09/11] fix broken regression test --- R/coord-cartesian-.r | 4 ++-- R/coord-flip.r | 2 +- tests/figs/deps.txt | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/R/coord-cartesian-.r b/R/coord-cartesian-.r index 24424ba531..d350801902 100644 --- a/R/coord-cartesian-.r +++ b/R/coord-cartesian-.r @@ -87,8 +87,8 @@ CoordCartesian <- ggproto("CoordCartesian", Coord, list(x = panel_params$x.range, y = panel_params$y.range) }, - backtransform_range = function(panel_params) { - list(x = panel_params$x.range, y = panel_params$y.range) + backtransform_range = function(self, panel_params) { + self$range(panel_params) }, transform = function(data, panel_params) { diff --git a/R/coord-flip.r b/R/coord-flip.r index ca85d5ce48..1d12a3b42c 100644 --- a/R/coord-flip.r +++ b/R/coord-flip.r @@ -44,7 +44,7 @@ CoordFlip <- ggproto("CoordFlip", CoordCartesian, CoordCartesian$transform(data, panel_params) }, - backtransform_range = function(panel_params) { + backtransform_range = function(self, panel_params) { self$range(panel_params) }, diff --git a/tests/figs/deps.txt b/tests/figs/deps.txt index bcd763e74f..ae13abdcb7 100644 --- a/tests/figs/deps.txt +++ b/tests/figs/deps.txt @@ -1,2 +1 @@ -ggplot2: 3.0.0.9000 vdiffr-svg-engine: 0.9000 From 288d5248f9a23dcbaf3e41cdb952574575c2a38a Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Tue, 18 Sep 2018 14:04:49 -0500 Subject: [PATCH 10/11] reinstate vdiffr deps --- tests/figs/deps.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/figs/deps.txt b/tests/figs/deps.txt index ae13abdcb7..bcd763e74f 100644 --- a/tests/figs/deps.txt +++ b/tests/figs/deps.txt @@ -1 +1,2 @@ +ggplot2: 3.0.0.9000 vdiffr-svg-engine: 0.9000 From bca85930e2c4a3db59a0702dd7ed94412da7d8ed Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Tue, 18 Sep 2018 14:07:08 -0500 Subject: [PATCH 11/11] revise news --- NEWS.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 114bbca213..b3e950e2b1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,9 +12,10 @@ (@clauswilke, #2846). * `Coord` objects now have a function `backtransform_range()` that returns the - panel range in data coordinates. This change may affect developers of custom coords. It - may also affect developers of custom geoms that use the `range()` function. In - some applications, `backtransform_range()` may be more appropriate. + panel range in data coordinates. This change may affect developers of custom coords, + who now should implement this function. It may also affect developers of custom + geoms that use the `range()` function. In some applications, `backtransform_range()` + may be more appropriate. (@clauswilke, #2821). * `geom_sf()` now respects `lineend`, `linejoin`, and `linemitre` parameters