Skip to content

Commit

Permalink
Nicer error message in coord-* functions (#4894)
Browse files Browse the repository at this point in the history
* Add `check_coord_limits` utility function

* Use `check_coord_limits` in all `coord-*` functions

* Update NEWS.md

* Update test-coord-* comments to better reflect expected behavior
  • Loading branch information
92amartins authored Jun 23, 2023
1 parent 996cbd8 commit 23508b3
Show file tree
Hide file tree
Showing 20 changed files with 132 additions and 0 deletions.
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# ggplot2 (development version)

* Nicer error messages for xlim/ylim arguments in coord-* functions
(@92amartins, #4601, #5297).

* `coord_sf()` now uses customisable guides provided in the scales or
`guides()` function (@teunbrand).

Expand Down
19 changes: 19 additions & 0 deletions R/coord-.R
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,22 @@ render_axis <- function(panel_params, axis, scale, position, theme) {
zeroGrob()
}
}

# Utility function to check coord limits
check_coord_limits <- function(
limits, arg = caller_arg(limits), call = caller_env()
) {
if (is.null(limits)) {
return(invisible(NULL))
}
if (!obj_is_vector(limits) || length(limits) != 2) {
what <- "{.obj_type_friendly {limits}}"
if (is.vector(limits)) {
what <- paste0(what, " of length {length(limits)}")
}
cli::cli_abort(
paste0("{.arg {arg}} must be a vector of length 2, not ", what, "."),
call = call
)
}
}
2 changes: 2 additions & 0 deletions R/coord-cartesian-.R
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
#' d + coord_cartesian(xlim = c(0, 1))
coord_cartesian <- function(xlim = NULL, ylim = NULL, expand = TRUE,
default = FALSE, clip = "on") {
check_coord_limits(xlim)
check_coord_limits(ylim)
ggproto(NULL, CoordCartesian,
limits = list(x = xlim, y = ylim),
expand = expand,
Expand Down
2 changes: 2 additions & 0 deletions R/coord-fixed.R
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#'
#' # Resize the plot to see that the specified aspect ratio is maintained
coord_fixed <- function(ratio = 1, xlim = NULL, ylim = NULL, expand = TRUE, clip = "on") {
check_coord_limits(xlim)
check_coord_limits(ylim)
ggproto(NULL, CoordFixed,
limits = list(x = xlim, y = ylim),
ratio = ratio,
Expand Down
2 changes: 2 additions & 0 deletions R/coord-flip.R
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#' geom_area() +
#' coord_flip()
coord_flip <- function(xlim = NULL, ylim = NULL, expand = TRUE, clip = "on") {
check_coord_limits(xlim)
check_coord_limits(ylim)
ggproto(NULL, CoordFlip,
limits = list(x = xlim, y = ylim),
expand = expand,
Expand Down
3 changes: 3 additions & 0 deletions R/coord-map.R
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ coord_map <- function(projection="mercator", ..., parameters = NULL, orientation
params <- parameters
}

check_coord_limits(xlim)
check_coord_limits(ylim)

ggproto(NULL, CoordMap,
projection = projection,
orientation = orientation,
Expand Down
2 changes: 2 additions & 0 deletions R/coord-quickmap.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#' @export
#' @rdname coord_map
coord_quickmap <- function(xlim = NULL, ylim = NULL, expand = TRUE, clip = "on") {
check_coord_limits(xlim)
check_coord_limits(ylim)
ggproto(NULL, CoordQuickmap,
limits = list(x = xlim, y = ylim),
expand = expand,
Expand Down
3 changes: 3 additions & 0 deletions R/coord-sf.R
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,9 @@ coord_sf <- function(xlim = NULL, ylim = NULL, expand = TRUE,
lims_method <- arg_match0(lims_method, c("cross", "box", "orthogonal", "geometry_bbox"))
}

check_coord_limits(xlim)
check_coord_limits(ylim)

ggproto(NULL, CoordSf,
limits = list(x = xlim, y = ylim),
lims_method = lims_method,
Expand Down
3 changes: 3 additions & 0 deletions R/coord-transform.R
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ coord_trans <- function(x = "identity", y = "identity", xlim = NULL, ylim = NULL
ylim <- limy
}

check_coord_limits(xlim)
check_coord_limits(ylim)

# resolve transformers
if (is.character(x)) x <- as.trans(x)
if (is.character(y)) y <- as.trans(y)
Expand Down
8 changes: 8 additions & 0 deletions tests/testthat/_snaps/coord-cartesian.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# cartesian coords throws error when limits are badly specified

`xlim` must be a vector of length 2, not a <ScaleContinuousPosition/ScaleContinuous/Scale/ggproto/gg> object.

---

`ylim` must be a vector of length 2, not an integer vector of length 3.

8 changes: 8 additions & 0 deletions tests/testthat/_snaps/coord-flip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# flip coords throws error when limits are badly specified

`xlim` must be a vector of length 2, not a <ScaleContinuousPosition/ScaleContinuous/Scale/ggproto/gg> object.

---

`ylim` must be a vector of length 2, not an integer vector of length 3.

8 changes: 8 additions & 0 deletions tests/testthat/_snaps/coord-map.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# coord map throws error when limits are badly specified

`xlim` must be a vector of length 2, not a <ScaleContinuousPosition/ScaleContinuous/Scale/ggproto/gg> object.

---

`ylim` must be a vector of length 2, not an integer vector of length 3.

8 changes: 8 additions & 0 deletions tests/testthat/_snaps/coord-transform.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# coord_trans() throws error when limits are badly specified

`xlim` must be a vector of length 2, not a <ScaleContinuousPosition/ScaleContinuous/Scale/ggproto/gg> object.

---

`ylim` must be a vector of length 2, not an integer vector of length 3.

8 changes: 8 additions & 0 deletions tests/testthat/_snaps/coord_sf.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,11 @@
Scale limits cannot be mapped onto spatial coordinates in `coord_sf()`
i Consider setting `lims_method = "geometry_bbox"` or `default_crs = NULL`.

# coord_sf() throws error when limits are badly specified

`xlim` must be a vector of length 2, not a <ScaleContinuousPosition/ScaleContinuous/Scale/ggproto/gg> object.

---

`ylim` must be a vector of length 2, not an integer vector of length 3.

13 changes: 13 additions & 0 deletions tests/testthat/test-coord-.R
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,16 @@ test_that("guide names are not removed by `train_panel_guides()`", {
expect_equal(names(layout$panel_params[[1]]$guides$aesthetics),
c("x", "y", "x.sec", "y.sec"))
})

test_that("check coord limits errors only on bad inputs", {
# Should return NULL if valid values are passed
expect_null(check_coord_limits(NULL))
expect_null(check_coord_limits(1:2))
expect_null(check_coord_limits(c(1,2)))

# Should raise error if Scale object is passed
expect_error(check_coord_limits(xlim(1,2)))

# Should raise error if vector of wrong length is passed
expect_error(check_coord_limits(1:3))
})
8 changes: 8 additions & 0 deletions tests/testthat/test-coord-cartesian.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ test_that("clipping can be turned off and on", {
expect_equal(coord$clip, "on")
})

test_that("cartesian coords throws error when limits are badly specified", {
# throws error when limit is a Scale object instead of vector
expect_snapshot_error(ggplot() + coord_cartesian(xlim(1,1)))

# throws error when limit's length is different than two
expect_snapshot_error(ggplot() + coord_cartesian(ylim=1:3))
})


# Visual tests ------------------------------------------------------------

Expand Down
8 changes: 8 additions & 0 deletions tests/testthat/test-coord-flip.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,11 @@ test_that("secondary labels are correctly turned off", {
coord_flip()
)
})

test_that("flip coords throws error when limits are badly specified", {
# throws error when limit is a Scale object instead of vector
expect_snapshot_error(ggplot() + coord_flip(xlim(1,1)))

# throws error when limit's length is different than two
expect_snapshot_error(ggplot() + coord_flip(ylim=1:3))
})
8 changes: 8 additions & 0 deletions tests/testthat/test-coord-map.R
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,11 @@ test_that("Inf is squished to range", {
expect_equal(d[[2]]$x, 0)
expect_equal(d[[2]]$y, 1)
})

test_that("coord map throws error when limits are badly specified", {
# throws error when limit is a Scale object instead of vector
expect_snapshot_error(ggplot() + coord_map(xlim=xlim(1,1)))

# throws error when limit's length is different than two
expect_snapshot_error(ggplot() + coord_cartesian(ylim=1:3))
})
8 changes: 8 additions & 0 deletions tests/testthat/test-coord-transform.R
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,11 @@ test_that("second axes display in coord_trans()", {
coord_trans(y = "log2")
)
})

test_that("coord_trans() throws error when limits are badly specified", {
# throws error when limit is a Scale object instead of vector
expect_snapshot_error(ggplot() + coord_trans(xlim=xlim(1,1)))

# throws error when limit's length is different than two
expect_snapshot_error(ggplot() + coord_trans(ylim=1:3))
})
8 changes: 8 additions & 0 deletions tests/testthat/test-coord_sf.R
Original file line number Diff line number Diff line change
Expand Up @@ -322,3 +322,11 @@ test_that("coord_sf() uses the guide system", {
p
)
})

test_that("coord_sf() throws error when limits are badly specified", {
# throws error when limit is a Scale object instead of vector
expect_snapshot_error(ggplot() + coord_sf(xlim(1,1)))

# throws error when limit's length is different than two
expect_snapshot_error(ggplot() + coord_sf(ylim=1:3))
})

0 comments on commit 23508b3

Please sign in to comment.