From 6319d3d6cffe6f893557d3cfdab67b8ff15f48e6 Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Tue, 4 Sep 2018 17:18:01 -0500 Subject: [PATCH 1/5] add explicit parsing option to labels in coord_sf() --- R/sf.R | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/R/sf.R b/R/sf.R index abcc60bceb..8f1736b316 100644 --- a/R/sf.R +++ b/R/sf.R @@ -383,6 +383,10 @@ scale_type.sfc <- function(x) "identity" #' @usage NULL #' @format NULL CoordSf <- ggproto("CoordSf", CoordCartesian, + # parameters that control the parsing of labels plotted in the + # N or E directions + parse_N_labels = FALSE, + parse_E_labels = FALSE, # Find the first CRS if not already supplied setup_params = function(self, data) { @@ -441,15 +445,22 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, # internal function used by setup_panel_params, # overrides the graticule labels based on scale settings if necessary fixup_graticule_labels = function(self, graticule, scale_x, scale_y, params = list()) { + needs_parsing <- rep(FALSE, nrow(graticule)) + needs_autoparsing <- rep(FALSE, nrow(graticule)) + x_breaks <- graticule$degree[graticule$type == "E"] if (is.null(scale_x$labels)) { x_labels <- rep(NA, length(x_breaks)) } else if (is.character(scale_x$labels)) { x_labels <- scale_x$labels + needs_parsing[graticule$type == "E"] <- self$parse_E_labels } else if (is.function(scale_x$labels)){ - x_labels <- scale_x$labels(x_breaks) + # all labels need to be character vectors + x_labels <- as.character(scale_x$labels(x_breaks)) + needs_parsing[graticule$type == "E"] <- self$parse_E_labels } else { x_labels <- graticule$degree_label[graticule$type == "E"] + needs_autoparsing[graticule$type == "E"] <- TRUE } if (length(x_labels) != length(x_breaks)) { stop("Breaks and labels along x direction are different lengths", call. = FALSE) @@ -462,10 +473,14 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, y_labels <- rep(NA, length(y_breaks)) } else if (is.character(scale_y$labels)) { y_labels <- scale_y$labels + needs_parsing[graticule$type == "N"] <- self$parse_N_labels } else if (is.function(scale_y$labels)){ - y_labels <- scale_y$labels(y_breaks) + # all labels need to be character vectors + y_labels <- as.character(scale_y$labels(y_breaks)) + needs_parsing[graticule$type == "N"] <- self$parse_N_labels } else { y_labels <- graticule$degree_label[graticule$type == "N"] + needs_autoparsing[graticule$type == "N"] <- TRUE } if (length(y_labels) != length(y_breaks)) { stop("Breaks and labels along y direction are different lengths", call. = FALSE) @@ -476,11 +491,12 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, if (!is.null(graticule$plot12)) graticule$degree_label[!graticule$plot12] <- NA - # Convert the string 'degree' to the degree symbol + # Parse labels if requested/needed has_degree <- grepl("\\bdegree\\b", graticule$degree_label) - if (any(has_degree)) { + needs_parsing <- needs_parsing | (needs_autoparsing & has_degree) + if (any(needs_parsing)) { labels <- as.list(graticule$degree_label) - labels[has_degree] <- parse_safe(graticule$degree_label[has_degree]) + labels[needs_parsing] <- parse_safe(graticule$degree_label[needs_parsing]) graticule$degree_label <- labels } @@ -604,12 +620,21 @@ sf_rescale01_x <- function(x, range) { #' use the CRS defined in the first layer. #' @param datum CRS that provides datum to use when generating graticules #' @param ndiscr number of segments to use for discretising graticule lines; -#' try increasing this when graticules look unexpected +#' try increasing this when graticules look unexpected +#' @param parse_N_labels If `TRUE`, labels indicating latitude (the degree to which +#' we are north or south) are parsed into R expressions before plotting. These +#' correspond to y-axis tick labels in a simple latitude-longitude plot. +#' Default is `FALSE`. +#' @param parse_E_labels If `TRUE`, labels indicating longitude (the degree to which +#' we are east or west) are parsed into R expressions before plotting. These +#' correspond to x-axis tick labels in a simple latitude-longitude plot. +#' Default is `FALSE`. #' @inheritParams coord_cartesian #' @export #' @rdname ggsf coord_sf <- function(xlim = NULL, ylim = NULL, expand = TRUE, crs = NULL, datum = sf::st_crs(4326), ndiscr = 100, + parse_N_labels = FALSE, parse_E_labels = FALSE, default = FALSE) { ggproto(NULL, CoordSf, limits = list(x = xlim, y = ylim), @@ -617,6 +642,8 @@ coord_sf <- function(xlim = NULL, ylim = NULL, expand = TRUE, crs = crs, ndiscr = ndiscr, expand = expand, + parse_N_labels = parse_N_labels, + parse_E_labels = parse_E_labels, default = default ) } From 3605a94f6f95bf2f213b51a9cfb67e59df778bd2 Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Tue, 4 Sep 2018 22:57:43 -0500 Subject: [PATCH 2/5] improved parsing logic, add regression tests --- NEWS.md | 2 +- R/sf.R | 47 +++++++---- man/ggsf.Rd | 13 ++- tests/testthat/test-coord_sf.R | 147 +++++++++++++++++++++++++++++++++ 4 files changed, 191 insertions(+), 18 deletions(-) diff --git a/NEWS.md b/NEWS.md index 7ec8955346..549c3635e1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,7 +5,7 @@ #2853). * `coord_sf()` now respects manual setting of axis tick labels (@clauswilke, - #2857). + #2857, #2881). * `geom_sf()` now respects `lineend`, `linejoin`, and `linemitre` parameters for lines and polygons (@alistaire47, #2826) diff --git a/R/sf.R b/R/sf.R index 8f1736b316..5d545793ac 100644 --- a/R/sf.R +++ b/R/sf.R @@ -451,17 +451,25 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, x_breaks <- graticule$degree[graticule$type == "E"] if (is.null(scale_x$labels)) { x_labels <- rep(NA, length(x_breaks)) - } else if (is.character(scale_x$labels)) { - x_labels <- scale_x$labels - needs_parsing[graticule$type == "E"] <- self$parse_E_labels - } else if (is.function(scale_x$labels)){ - # all labels need to be character vectors - x_labels <- as.character(scale_x$labels(x_breaks)) - needs_parsing[graticule$type == "E"] <- self$parse_E_labels - } else { + } else if (is.waive(scale_x$labels)) { x_labels <- graticule$degree_label[graticule$type == "E"] needs_autoparsing[graticule$type == "E"] <- TRUE + } else { + if (is.function(scale_x$labels)) { + x_labels <- scale_x$labels(x_breaks) + } else { + x_labels <- scale_x$labels + } + + if (is.character(x_labels)) { + needs_parsing[graticule$type == "E"] <- self$parse_E_labels + } else { + # all labels need to be temporarily stored as character vectors + x_labels <- as.character(x_labels) + needs_parsing[graticule$type == "E"] <- TRUE + } } + if (length(x_labels) != length(x_breaks)) { stop("Breaks and labels along x direction are different lengths", call. = FALSE) } @@ -471,16 +479,23 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, y_breaks <- graticule$degree[graticule$type == "N"] if (is.null(scale_y$labels)) { y_labels <- rep(NA, length(y_breaks)) - } else if (is.character(scale_y$labels)) { - y_labels <- scale_y$labels - needs_parsing[graticule$type == "N"] <- self$parse_N_labels - } else if (is.function(scale_y$labels)){ - # all labels need to be character vectors - y_labels <- as.character(scale_y$labels(y_breaks)) - needs_parsing[graticule$type == "N"] <- self$parse_N_labels - } else { + } else if (is.waive(scale_y$labels)) { y_labels <- graticule$degree_label[graticule$type == "N"] needs_autoparsing[graticule$type == "N"] <- TRUE + } else { + if (is.function(scale_y$labels)) { + y_labels <- scale_y$labels(y_breaks) + } else { + y_labels <- scale_y$labels + } + + if (is.character(y_labels)) { + needs_parsing[graticule$type == "N"] <- self$parse_N_labels + } else { + # all labels need to be temporarily stored as character vectors + y_labels <- as.character(y_labels) + needs_parsing[graticule$type == "N"] <- TRUE + } } if (length(y_labels) != length(y_breaks)) { stop("Breaks and labels along y direction are different lengths", call. = FALSE) diff --git a/man/ggsf.Rd b/man/ggsf.Rd index 9bb16eb742..c9454ed7c8 100644 --- a/man/ggsf.Rd +++ b/man/ggsf.Rd @@ -33,7 +33,8 @@ geom_sf_text(mapping = aes(), data = NULL, stat = "sf_coordinates", show.legend = NA, inherit.aes = TRUE, fun.geometry = NULL) coord_sf(xlim = NULL, ylim = NULL, expand = TRUE, crs = NULL, - datum = sf::st_crs(4326), ndiscr = 100, default = FALSE) + datum = sf::st_crs(4326), ndiscr = 100, parse_N_labels = FALSE, + parse_E_labels = FALSE, default = FALSE) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[=aes]{aes()}} or @@ -123,6 +124,16 @@ use the CRS defined in the first layer.} \item{ndiscr}{number of segments to use for discretising graticule lines; try increasing this when graticules look unexpected} +\item{parse_N_labels}{If \code{TRUE}, labels indicating latitude (the degree to which +we are north or south) are parsed into R expressions before plotting. These +correspond to y-axis tick labels in a simple latitude-longitude plot. +Default is \code{FALSE}.} + +\item{parse_E_labels}{If \code{TRUE}, labels indicating longitude (the degree to which +we are east or west) are parsed into R expressions before plotting. These +correspond to x-axis tick labels in a simple latitude-longitude plot. +Default is \code{FALSE}.} + \item{default}{Is this the default coordinate system? If \code{FALSE} (the default), then replacing this coordinate system with another one creates a message alerting the user that the coordinate system is being replaced. If \code{TRUE}, that warning diff --git a/tests/testthat/test-coord_sf.R b/tests/testthat/test-coord_sf.R index 9996dfe6b8..d651789673 100644 --- a/tests/testthat/test-coord_sf.R +++ b/tests/testthat/test-coord_sf.R @@ -14,3 +14,150 @@ test_that("multiplication works", { skip("sf tests are currently unstable") expect_doppelganger("sf-polygons", plot) }) + + +test_that("axis labels can be set manually", { + skip_if_not_installed("sf") + + plot <- ggplot(sf::st_polygon(list(matrix(1e3*c(1, 2, 3, 1, 1, 3, 2, 1), ncol = 2)))) + + geom_sf() + + # autogenerated labels + b <- ggplot_build( + plot + + scale_x_continuous(breaks = c(1000, 2000, 3000)) + + scale_y_continuous(breaks = c(1000, 1500, 2000)) + ) + graticule <- b$layout$panel_params[[1]]$graticule + expect_identical( + graticule[graticule$type == "E", ]$degree_label, + c("1000", "2000", "3000") + ) + expect_identical( + graticule[graticule$type == "N", ]$degree_label, + c("1000", "1500", "2000") + ) + + # character labels + b <- ggplot_build( + plot + + scale_x_continuous( + breaks = c(1000, 2000, 3000), + labels = c("A", "B", "C") + ) + + scale_y_continuous( + breaks = c(1000, 1500, 2000), + labels = c("D", "E", "F") + ) + ) + graticule <- b$layout$panel_params[[1]]$graticule + expect_identical( + graticule[graticule$type == "E", ]$degree_label, + c("A", "B", "C") + ) + expect_identical( + graticule[graticule$type == "N", ]$degree_label, + c("D", "E", "F") + ) + + # expressions mixed with character labels + b <- ggplot_build( + plot + + scale_x_continuous( + breaks = c(1000, 2000, 3000), + labels = c("A", "B", "C") + ) + + scale_y_continuous( + breaks = c(1000, 1500, 2000), + labels = parse(text = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3")) + ) + ) + graticule <- b$layout$panel_params[[1]]$graticule + expect_identical( + graticule[graticule$type == "E", ]$degree_label, + as.list(c("A", "B", "C")) + ) + parsed <- vector("list", 3) + parsed[1:3] <- parse(text = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3")) + expect_identical( + graticule[graticule$type == "N", ]$degree_label, + parsed + ) + + # parsing via coord_sf() + b <- ggplot_build( + plot + + scale_x_continuous( + breaks = c(1000, 2000, 3000), + labels = c("10^3", "2 %*% 10^3", "3 %*% 10^3") + ) + + scale_y_continuous( + breaks = c(1000, 1500, 2000), + labels = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3") + ) + + coord_sf(parse_E_labels = TRUE, parse_N_labels = FALSE) + ) + graticule <- b$layout$panel_params[[1]]$graticule + parsed <- vector("list", 3) + parsed[1:3] <- parse(text = c("10^3", "2 %*% 10^3", "3 %*% 10^3")) + expect_identical( + graticule[graticule$type == "E", ]$degree_label, + parsed + ) + expect_identical( + graticule[graticule$type == "N", ]$degree_label, + as.list(c("10^3", "1.5 %*% 10^3", "2 %*% 10^3")) + ) + + b <- ggplot_build( + plot + + scale_x_continuous( + breaks = c(1000, 2000, 3000), + labels = c("10^3", "2 %*% 10^3", "3 %*% 10^3") + ) + + scale_y_continuous( + breaks = c(1000, 1500, 2000), + labels = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3") + ) + + coord_sf(parse_E_labels = FALSE, parse_N_labels = TRUE) + ) + graticule <- b$layout$panel_params[[1]]$graticule + expect_identical( + graticule[graticule$type == "E", ]$degree_label, + as.list(c("10^3", "2 %*% 10^3", "3 %*% 10^3")) + ) + parsed <- vector("list", 3) + parsed[1:3] <- parse(text = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3")) + expect_identical( + graticule[graticule$type == "N", ]$degree_label, + parsed + ) + + # autoparsing of degree labels + data <- sf::st_sfc( + sf::st_polygon(list(matrix(1e1*c(1, 2, 3, 1, 1, 3, 2, 1), ncol = 2))), + crs = 4326 # basic long-lat crs + ) + + plot <- ggplot(data) + geom_sf() + + b <- ggplot_build( + plot + + scale_x_continuous(breaks = c(10, 20, 30)) + + scale_y_continuous(breaks = c(10, 15, 20)) + ) + graticule <- b$layout$panel_params[[1]]$graticule + parsed <- vector("list", 3) + parsed[1:3] <- parse(text = c("10*degree*E", "20*degree*E", "30*degree*E")) + expect_identical( + graticule[graticule$type == "E", ]$degree_label, + parsed + ) + parsed[1:3] <- parse(text = c("10*degree*N", "15*degree*N", "20*degree*N")) + expect_identical( + graticule[graticule$type == "N", ]$degree_label, + parsed + ) + +}) + From e36178243bc2b2abfb2e7e017cdeaa1c2adc4c9d Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Thu, 13 Sep 2018 00:00:57 -0500 Subject: [PATCH 3/5] remove option for explicit parsing, not needed --- R/sf.R | 19 ++-------------- man/ggsf.Rd | 13 +---------- tests/testthat/test-coord_sf.R | 41 +++++++--------------------------- 3 files changed, 11 insertions(+), 62 deletions(-) diff --git a/R/sf.R b/R/sf.R index 5d545793ac..e68d508e73 100644 --- a/R/sf.R +++ b/R/sf.R @@ -383,10 +383,6 @@ scale_type.sfc <- function(x) "identity" #' @usage NULL #' @format NULL CoordSf <- ggproto("CoordSf", CoordCartesian, - # parameters that control the parsing of labels plotted in the - # N or E directions - parse_N_labels = FALSE, - parse_E_labels = FALSE, # Find the first CRS if not already supplied setup_params = function(self, data) { @@ -462,7 +458,7 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, } if (is.character(x_labels)) { - needs_parsing[graticule$type == "E"] <- self$parse_E_labels + needs_parsing[graticule$type == "E"] <- FALSE } else { # all labels need to be temporarily stored as character vectors x_labels <- as.character(x_labels) @@ -490,7 +486,7 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, } if (is.character(y_labels)) { - needs_parsing[graticule$type == "N"] <- self$parse_N_labels + needs_parsing[graticule$type == "N"] <- FALSE } else { # all labels need to be temporarily stored as character vectors y_labels <- as.character(y_labels) @@ -636,20 +632,11 @@ sf_rescale01_x <- function(x, range) { #' @param datum CRS that provides datum to use when generating graticules #' @param ndiscr number of segments to use for discretising graticule lines; #' try increasing this when graticules look unexpected -#' @param parse_N_labels If `TRUE`, labels indicating latitude (the degree to which -#' we are north or south) are parsed into R expressions before plotting. These -#' correspond to y-axis tick labels in a simple latitude-longitude plot. -#' Default is `FALSE`. -#' @param parse_E_labels If `TRUE`, labels indicating longitude (the degree to which -#' we are east or west) are parsed into R expressions before plotting. These -#' correspond to x-axis tick labels in a simple latitude-longitude plot. -#' Default is `FALSE`. #' @inheritParams coord_cartesian #' @export #' @rdname ggsf coord_sf <- function(xlim = NULL, ylim = NULL, expand = TRUE, crs = NULL, datum = sf::st_crs(4326), ndiscr = 100, - parse_N_labels = FALSE, parse_E_labels = FALSE, default = FALSE) { ggproto(NULL, CoordSf, limits = list(x = xlim, y = ylim), @@ -657,8 +644,6 @@ coord_sf <- function(xlim = NULL, ylim = NULL, expand = TRUE, crs = crs, ndiscr = ndiscr, expand = expand, - parse_N_labels = parse_N_labels, - parse_E_labels = parse_E_labels, default = default ) } diff --git a/man/ggsf.Rd b/man/ggsf.Rd index c9454ed7c8..9bb16eb742 100644 --- a/man/ggsf.Rd +++ b/man/ggsf.Rd @@ -33,8 +33,7 @@ geom_sf_text(mapping = aes(), data = NULL, stat = "sf_coordinates", show.legend = NA, inherit.aes = TRUE, fun.geometry = NULL) coord_sf(xlim = NULL, ylim = NULL, expand = TRUE, crs = NULL, - datum = sf::st_crs(4326), ndiscr = 100, parse_N_labels = FALSE, - parse_E_labels = FALSE, default = FALSE) + datum = sf::st_crs(4326), ndiscr = 100, default = FALSE) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[=aes]{aes()}} or @@ -124,16 +123,6 @@ use the CRS defined in the first layer.} \item{ndiscr}{number of segments to use for discretising graticule lines; try increasing this when graticules look unexpected} -\item{parse_N_labels}{If \code{TRUE}, labels indicating latitude (the degree to which -we are north or south) are parsed into R expressions before plotting. These -correspond to y-axis tick labels in a simple latitude-longitude plot. -Default is \code{FALSE}.} - -\item{parse_E_labels}{If \code{TRUE}, labels indicating longitude (the degree to which -we are east or west) are parsed into R expressions before plotting. These -correspond to x-axis tick labels in a simple latitude-longitude plot. -Default is \code{FALSE}.} - \item{default}{Is this the default coordinate system? If \code{FALSE} (the default), then replacing this coordinate system with another one creates a message alerting the user that the coordinate system is being replaced. If \code{TRUE}, that warning diff --git a/tests/testthat/test-coord_sf.R b/tests/testthat/test-coord_sf.R index d651789673..f84efcb849 100644 --- a/tests/testthat/test-coord_sf.R +++ b/tests/testthat/test-coord_sf.R @@ -84,52 +84,27 @@ test_that("axis labels can be set manually", { parsed ) - # parsing via coord_sf() + # reverse x and y from previous test b <- ggplot_build( plot + - scale_x_continuous( - breaks = c(1000, 2000, 3000), - labels = c("10^3", "2 %*% 10^3", "3 %*% 10^3") - ) + scale_y_continuous( - breaks = c(1000, 1500, 2000), - labels = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3") - ) + - coord_sf(parse_E_labels = TRUE, parse_N_labels = FALSE) - ) - graticule <- b$layout$panel_params[[1]]$graticule - parsed <- vector("list", 3) - parsed[1:3] <- parse(text = c("10^3", "2 %*% 10^3", "3 %*% 10^3")) - expect_identical( - graticule[graticule$type == "E", ]$degree_label, - parsed - ) - expect_identical( - graticule[graticule$type == "N", ]$degree_label, - as.list(c("10^3", "1.5 %*% 10^3", "2 %*% 10^3")) - ) - - b <- ggplot_build( - plot + - scale_x_continuous( breaks = c(1000, 2000, 3000), - labels = c("10^3", "2 %*% 10^3", "3 %*% 10^3") + labels = c("A", "B", "C") ) + - scale_y_continuous( + scale_x_continuous( breaks = c(1000, 1500, 2000), - labels = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3") - ) + - coord_sf(parse_E_labels = FALSE, parse_N_labels = TRUE) + labels = parse(text = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3")) + ) ) graticule <- b$layout$panel_params[[1]]$graticule expect_identical( - graticule[graticule$type == "E", ]$degree_label, - as.list(c("10^3", "2 %*% 10^3", "3 %*% 10^3")) + graticule[graticule$type == "N", ]$degree_label, + as.list(c("A", "B", "C")) ) parsed <- vector("list", 3) parsed[1:3] <- parse(text = c("10^3", "1.5 %*% 10^3", "2 %*% 10^3")) expect_identical( - graticule[graticule$type == "N", ]$degree_label, + graticule[graticule$type == "E", ]$degree_label, parsed ) From 6527b4f9ac4987e110c971dea7668f6c03532e17 Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Thu, 13 Sep 2018 00:24:26 -0500 Subject: [PATCH 4/5] handle factors correctly --- R/sf.R | 14 ++++++++------ tests/testthat/test-coord_sf.R | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/R/sf.R b/R/sf.R index e68d508e73..37ce3675ac 100644 --- a/R/sf.R +++ b/R/sf.R @@ -457,13 +457,14 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, x_labels <- scale_x$labels } - if (is.character(x_labels)) { + # all labels need to be temporarily stored as character vectors, + # but expressions need to be parsed afterwards + if (is.character(x_labels) || is.factor(x_labels)) { needs_parsing[graticule$type == "E"] <- FALSE } else { - # all labels need to be temporarily stored as character vectors - x_labels <- as.character(x_labels) needs_parsing[graticule$type == "E"] <- TRUE } + x_labels <- as.character(x_labels) } if (length(x_labels) != length(x_breaks)) { @@ -485,13 +486,14 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, y_labels <- scale_y$labels } - if (is.character(y_labels)) { + # all labels need to be temporarily stored as character vectors, + # but expressions need to be parsed afterwards + if (is.character(y_labels) || is.factor(y_labels)) { needs_parsing[graticule$type == "N"] <- FALSE } else { - # all labels need to be temporarily stored as character vectors - y_labels <- as.character(y_labels) needs_parsing[graticule$type == "N"] <- TRUE } + y_labels <- as.character(y_labels) } if (length(y_labels) != length(y_breaks)) { stop("Breaks and labels along y direction are different lengths", call. = FALSE) diff --git a/tests/testthat/test-coord_sf.R b/tests/testthat/test-coord_sf.R index f84efcb849..4db7937a9f 100644 --- a/tests/testthat/test-coord_sf.R +++ b/tests/testthat/test-coord_sf.R @@ -60,6 +60,30 @@ test_that("axis labels can be set manually", { c("D", "E", "F") ) + # factors are treated like character labels + # and are not parsed + b <- ggplot_build( + plot + + scale_x_continuous( + breaks = c(1000, 2000, 3000), + labels = factor(c("A", "B", "C")) + ) + + scale_y_continuous( + breaks = c(1000, 1500, 2000), + labels = factor(c("1 * degree * N", "1.5 * degree * N", "2 * degree * N")) + ) + ) + graticule <- b$layout$panel_params[[1]]$graticule + expect_identical( + graticule[graticule$type == "E", ]$degree_label, + c("A", "B", "C") + ) + expect_identical( + graticule[graticule$type == "N", ]$degree_label, + c("1 * degree * N", "1.5 * degree * N", "2 * degree * N") + ) + + # expressions mixed with character labels b <- ggplot_build( plot + From a055d6d18b103807b9a9036e5f20c6924cd3f906 Mon Sep 17 00:00:00 2001 From: Claus Wilke Date: Thu, 13 Sep 2018 17:05:19 -0500 Subject: [PATCH 5/5] simplify code --- R/sf.R | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/R/sf.R b/R/sf.R index 37ce3675ac..2a7eb5b784 100644 --- a/R/sf.R +++ b/R/sf.R @@ -459,11 +459,7 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, # all labels need to be temporarily stored as character vectors, # but expressions need to be parsed afterwards - if (is.character(x_labels) || is.factor(x_labels)) { - needs_parsing[graticule$type == "E"] <- FALSE - } else { - needs_parsing[graticule$type == "E"] <- TRUE - } + needs_parsing[graticule$type == "E"] <- !(is.character(x_labels) || is.factor(x_labels)) x_labels <- as.character(x_labels) } @@ -488,13 +484,10 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, # all labels need to be temporarily stored as character vectors, # but expressions need to be parsed afterwards - if (is.character(y_labels) || is.factor(y_labels)) { - needs_parsing[graticule$type == "N"] <- FALSE - } else { - needs_parsing[graticule$type == "N"] <- TRUE - } + needs_parsing[graticule$type == "N"] <- !(is.character(y_labels) || is.factor(y_labels)) y_labels <- as.character(y_labels) } + if (length(y_labels) != length(y_breaks)) { stop("Breaks and labels along y direction are different lengths", call. = FALSE) }