Skip to content

Commit 4193a50

Browse files
authored
Non-orthogonal coords preserve AsIs x/y variables (#6206)
* exempt some coords from transforming x/y AsIs variables * add tests * add news bullet * throw warning when only one of two variables is AsIs * update snapshot
1 parent 949d359 commit 4193a50

File tree

8 files changed

+81
-0
lines changed

8 files changed

+81
-0
lines changed

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# ggplot2 (development version)
22

3+
* In non-orthogonal coordinate systems (`coord_sf()`, `coord_polar()` and
4+
`coord_radial()`), using 'AsIs' variables escape transformation when
5+
both `x` and `y` is an 'AsIs' variable (@teunbrand, #6205).
36
* The following methods have been deprecated: `fortify.lm()`, `fortify.glht()`,
47
`fortify.confint.glht()`, `fortify.summary.glht()` and `fortify.cld()`. It
58
is recommend to use `broom::augment()` and `broom::tidy()` instead

R/coord-.R

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,24 @@ check_coord_limits <- function(
284284
check_object(limits, is_vector, "a vector", arg = arg, call = call)
285285
check_length(limits, 2L, arg = arg, call = call)
286286
}
287+
288+
is_transform_immune <- function(data, coord_name) {
289+
x <- inherits(data$x, "AsIs")
290+
y <- inherits(data$y, "AsIs")
291+
if (!(x || y)) {
292+
# Neither variable is AsIs, so we need to transform
293+
return(FALSE)
294+
}
295+
if (x && y) {
296+
# Both variables are AsIs, so no need to transform
297+
return(TRUE)
298+
}
299+
# We're now in the `xor(x, y)` case
300+
var <- if (x) "x" else "y"
301+
alt <- if (x) "y" else "x"
302+
cli::cli_warn(
303+
"{.fn {coord_name}} cannot respect the {.cls AsIs} class of {.var {var}} \\
304+
when {.var {alt}} is not also {.cls AsIs}."
305+
)
306+
return(FALSE)
307+
}

R/coord-polar.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ CoordPolar <- ggproto("CoordPolar", Coord,
180180
},
181181

182182
transform = function(self, data, panel_params) {
183+
if (is_transform_immune(data, snake_class(self))) {
184+
return(data)
185+
}
186+
183187
arc <- self$start + c(0, 2 * pi)
184188
dir <- self$direction
185189
data <- rename_data(self, data)

R/coord-radial.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,10 @@ CoordRadial <- ggproto("CoordRadial", Coord,
275275
},
276276

277277
transform = function(self, data, panel_params) {
278+
if (is_transform_immune(data, snake_class(self))) {
279+
return(data)
280+
}
281+
278282
data <- rename_data(self, data)
279283
bbox <- panel_params$bbox %||% list(x = c(0, 1), y = c(0, 1))
280284
arc <- panel_params$arc %||% c(0, 2 * pi)

R/coord-sf.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ CoordSf <- ggproto("CoordSf", CoordCartesian,
7777
},
7878

7979
transform = function(self, data, panel_params) {
80+
if (is_transform_immune(data, snake_class(self))) {
81+
return(data)
82+
}
83+
8084
# we need to transform all non-sf data into the correct coordinate system
8185
source_crs <- panel_params$default_crs
8286
target_crs <- panel_params$crs

tests/testthat/_snaps/coord-polar.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,7 @@
1212
No appropriate placement found for `r_axis_inside`.
1313
i Axis will be placed at panel edge.
1414

15+
# when both x and y are AsIs, they are not transformed
16+
17+
`coord_radial()` cannot respect the <AsIs> class of `x` when `y` is not also <AsIs>.
18+

tests/testthat/test-coord-polar.R

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,31 @@ test_that("bounding box calculations are sensible", {
155155
)
156156
})
157157

158+
test_that("when both x and y are AsIs, they are not transformed", {
159+
160+
p <- ggplot() +
161+
annotate("text", x = I(0.75), y = I(0.25), label = "foo") +
162+
scale_x_continuous(limits = c(0, 10)) +
163+
scale_y_continuous(limits = c(0, 10))
164+
165+
grob <- get_layer_grob(p + coord_polar())[[1]]
166+
location <- c(as.numeric(grob$x), as.numeric(grob$y))
167+
expect_equal(location, c(0.75, 0.25))
168+
169+
grob <- get_layer_grob(p + coord_radial())[[1]]
170+
location <- c(as.numeric(grob$x), as.numeric(grob$y))
171+
expect_equal(location, c(0.75, 0.25))
172+
173+
# Check warning is thrown if only one is AsIs
174+
p <- ggplot() +
175+
annotate("text", x = I(0.75), y = 2.5, label = "foo") +
176+
scale_x_continuous(limits = c(0, 10)) +
177+
scale_y_continuous(limits = c(0, 10)) +
178+
coord_radial()
179+
180+
expect_snapshot_warning(ggplotGrob(p))
181+
182+
})
158183

159184
# Visual tests ------------------------------------------------------------
160185

tests/testthat/test-coord_sf.R

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,22 @@ test_that("sf_transform_xy() works", {
314314

315315
})
316316

317+
test_that("when both x and y are AsIs, they are not transformed", {
318+
319+
skip_if_not_installed("sf")
320+
321+
p <- ggplot() +
322+
annotate("text", x = I(0.75), y = I(0.25), label = "foo") +
323+
scale_x_continuous(limits = c(-180, 180)) +
324+
scale_y_continuous(limits = c(-80, 80)) +
325+
coord_sf(default_crs = 4326, crs = 3857)
326+
327+
grob <- get_layer_grob(p)[[1]]
328+
location <- c(as.numeric(grob$x), as.numeric(grob$y))
329+
expect_equal(location, c(0.75, 0.25))
330+
331+
})
332+
317333
test_that("coord_sf() can use function breaks and n.breaks", {
318334

319335
polygon <- sf::st_sfc(

0 commit comments

Comments
 (0)