diff --git a/DESCRIPTION b/DESCRIPTION index ec4c1e986a..8a03010d08 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -199,6 +199,7 @@ Collate: 'scale-shape.r' 'scale-size.r' 'scale-type.R' + 'scale-view.r' 'scale-viridis.r' 'scales-.r' 'stat-bin.r' diff --git a/R/coord-.r b/R/coord-.r index d29bd420e7..68c48d5291 100644 --- a/R/coord-.r +++ b/R/coord-.r @@ -64,51 +64,27 @@ Coord <- ggproto("Coord", render_fg = function(panel_params, theme) element_render(theme, "panel.border"), render_bg = function(panel_params, theme) { - guide_grid(theme, - panel_params$x.minor, - panel_params$x.major, - panel_params$y.minor, - panel_params$y.major) + stop("Not implemented", call. = FALSE) }, render_axis_h = function(panel_params, theme) { - arrange <- panel_params$x.arrange %||% c("secondary", "primary") - - list( - top = render_axis(panel_params, arrange[1], "x", "top", theme), - bottom = render_axis(panel_params, arrange[2], "x", "bottom", theme) - ) + stop("Not implemented", call. = FALSE) }, render_axis_v = function(panel_params, theme) { - arrange <- panel_params$y.arrange %||% c("primary", "secondary") - - list( - left = render_axis(panel_params, arrange[1], "y", "left", theme), - right = render_axis(panel_params, arrange[2], "y", "right", theme) - ) + stop("Not implemented", call. = FALSE) }, # transform range given in transformed coordinates # back into range in given in (possibly scale-transformed) # data coordinates backtransform_range = function(self, panel_params) { - warning( - "range backtransformation not implemented in this coord; results may be wrong.", - call. = FALSE - ) - # return result from range function for backwards compatibility - # before ggplot2 3.0.1 - self$range(panel_params) + stop("Not implemented", call. = FALSE) }, # return range stored in panel_params range = function(panel_params) { - warning( - "range calculation not implemented in this coord; results may be wrong.", - call. = FALSE - ) - list(x = panel_params$x.range, y = panel_params$y.range) + stop("Not implemented", call. = FALSE) }, setup_panel_params = function(scale_x, scale_y, params = list()) { diff --git a/R/coord-cartesian-.r b/R/coord-cartesian-.r index d350801902..8efedd271c 100644 --- a/R/coord-cartesian-.r +++ b/R/coord-cartesian-.r @@ -79,12 +79,12 @@ CoordCartesian <- ggproto("CoordCartesian", Coord, is_free = function() TRUE, distance = function(x, y, panel_params) { - max_dist <- dist_euclidean(panel_params$x.range, panel_params$y.range) + max_dist <- dist_euclidean(panel_params$x$dimension(), panel_params$y$dimension()) dist_euclidean(x, y) / max_dist }, range = function(panel_params) { - list(x = panel_params$x.range, y = panel_params$y.range) + list(x = panel_params$x$dimension(), y = panel_params$y$dimension()) }, backtransform_range = function(self, panel_params) { @@ -92,37 +92,78 @@ CoordCartesian <- ggproto("CoordCartesian", Coord, }, transform = function(data, panel_params) { - rescale_x <- function(data) rescale(data, from = panel_params$x.range) - rescale_y <- function(data) rescale(data, from = panel_params$y.range) - - data <- transform_position(data, rescale_x, rescale_y) + data <- transform_position(data, panel_params$x$rescale, panel_params$y$rescale) transform_position(data, squish_infinite, squish_infinite) }, setup_panel_params = function(self, scale_x, scale_y, params = list()) { - train_cartesian <- function(scale, limits, name) { - range <- scale_range(scale, limits, self$expand) + c( + view_scales_from_scale(scale_x, self$limits$x, self$expand), + view_scales_from_scale(scale_y, self$limits$y, self$expand) + ) + }, + + render_bg = function(panel_params, theme) { + guide_grid( + theme, + panel_params$x$break_positions_minor(), + panel_params$x$break_positions(), + panel_params$y$break_positions_minor(), + panel_params$y$break_positions() + ) + }, - out <- scale$break_info(range) - out$arrange <- scale$axis_order() - names(out) <- paste(name, names(out), sep = ".") - out - } + render_axis_h = function(panel_params, theme) { + arrange <- panel_params$x.arrange %||% c("secondary", "primary") + arrange_scale_keys <- c("primary" = "x", "secondary" = "x.sec")[arrange] + arrange_scales <- panel_params[arrange_scale_keys] - c( - train_cartesian(scale_x, self$limits$x, "x"), - train_cartesian(scale_y, self$limits$y, "y") + list( + top = draw_view_scale_axis(arrange_scales[[1]], "top", theme), + bottom = draw_view_scale_axis(arrange_scales[[2]], "bottom", theme) + ) + }, + + render_axis_v = function(panel_params, theme) { + arrange <- panel_params$y.arrange %||% c("primary", "secondary") + arrange_scale_keys <- c("primary" = "y", "secondary" = "y.sec")[arrange] + arrange_scales <- panel_params[arrange_scale_keys] + + list( + left = draw_view_scale_axis(arrange_scales[[1]], "left", theme), + right = draw_view_scale_axis(arrange_scales[[2]], "right", theme) ) } ) -scale_range <- function(scale, limits = NULL, expand = TRUE) { - expansion <- if (expand) expand_default(scale) else c(0, 0) +view_scales_from_scale <- function(scale, coord_limits = NULL, expand = TRUE) { + expansion <- if (expand) expand_default(scale) else expand_scale(0, 0) + limits <- scale$get_limits() - if (is.null(limits)) { - scale$dimension(expansion) + if (is.null(coord_limits)) { + continuous_range <- scale$dimension(expansion, limits) } else { - range <- range(scale$transform(limits)) - expand_range(range, expansion[1], expansion[2]) + continuous_range <- range(scale$transform(coord_limits)) + continuous_range <- expand_range4(continuous_range, expansion) + } + + aesthetic <- scale$aesthetics[1] + + view_scales <- list( + view_scale_primary(scale, limits, continuous_range), + sec = view_scale_secondary(scale, limits, continuous_range), + arrange = scale$axis_order(), + range = continuous_range + ) + names(view_scales) <- c(aesthetic, paste0(aesthetic, ".", names(view_scales)[-1])) + + view_scales +} + +draw_view_scale_axis <- function(view_scale, axis_position, theme) { + if(is.null(view_scale) || view_scale$is_empty()) { + return(zeroGrob()) } + + draw_axis(view_scale$break_positions(), view_scale$get_labels(), axis_position, theme) } diff --git a/R/coord-flip.r b/R/coord-flip.r index 1d12a3b42c..71d11f26ec 100644 --- a/R/coord-flip.r +++ b/R/coord-flip.r @@ -48,10 +48,11 @@ CoordFlip <- ggproto("CoordFlip", CoordCartesian, self$range(panel_params) }, - range = function(panel_params) { + range = function(self, 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) + un_flipped_range <- ggproto_parent(CoordCartesian, self)$range(panel_params) + list(x = un_flipped_range$y, y = un_flipped_range$x) }, setup_panel_params = function(self, scale_x, scale_y, params = list()) { diff --git a/R/coord-sf.R b/R/coord-sf.R index 20b0d35b79..00d932b9fb 100644 --- a/R/coord-sf.R +++ b/R/coord-sf.R @@ -466,3 +466,14 @@ parse_axes_labeling <- function(x) { labs = unlist(strsplit(x, "")) list(top = labs[1], right = labs[2], bottom = labs[3], left = labs[4]) } + +scale_range <- function(scale, limits = NULL, expand = TRUE) { + expansion <- if (expand) expand_default(scale) else expand_scale(0, 0) + + if (is.null(limits)) { + scale$dimension(expansion) + } else { + continuous_range <- range(scale$transform(limits)) + expand_range4(continuous_range, expansion) + } +} diff --git a/R/coord-transform.r b/R/coord-transform.r index 237c9dbe1f..992ed31d45 100644 --- a/R/coord-transform.r +++ b/R/coord-transform.r @@ -150,6 +150,34 @@ CoordTrans <- ggproto("CoordTrans", Coord, train_trans(scale_x, self$limits$x, self$trans$x, "x"), train_trans(scale_y, self$limits$y, self$trans$y, "y") ) + }, + + render_bg = function(panel_params, theme) { + guide_grid( + theme, + panel_params$x.minor, + panel_params$x.major, + panel_params$y.minor, + panel_params$y.major + ) + }, + + render_axis_h = function(panel_params, theme) { + arrange <- panel_params$x.arrange %||% c("secondary", "primary") + + list( + top = render_axis(panel_params, arrange[1], "x", "top", theme), + bottom = render_axis(panel_params, arrange[2], "x", "bottom", theme) + ) + }, + + render_axis_v = function(panel_params, theme) { + arrange <- panel_params$y.arrange %||% c("primary", "secondary") + + list( + left = render_axis(panel_params, arrange[1], "y", "left", theme), + right = render_axis(panel_params, arrange[2], "y", "right", theme) + ) } ) diff --git a/R/scale-.r b/R/scale-.r index 40c1ef33a5..0d39d0f2e5 100644 --- a/R/scale-.r +++ b/R/scale-.r @@ -1,11 +1,275 @@ + +#' Continuous scale constructor +#' +#' @export +#' @param aesthetics The names of the aesthetics that this scale works with. +#' @param scale_name The name of the scale that should be used for error messages +#' associated with this scale. +#' @param palette A palette function that when called with a numeric vector with +#' values between 0 and 1 returns the corresponding output values +#' (e.g., [scales::area_pal()]). +#' @param name The name of the scale. Used as the axis or legend title. If +#' `waiver()`, the default, the name of the scale is taken from the first +#' mapping used for that aesthetic. If `NULL`, the legend title will be +#' omitted. +#' @param breaks One of: +#' - `NULL` for no breaks +#' - `waiver()` for the default breaks computed by the +#' [transformation object][scales::trans_new()] +#' - A numeric vector of positions +#' - A function that takes the limits as input and returns breaks +#' as output (e.g., a function returned by [scales::extended_breaks()]) +#' @param minor_breaks One of: +#' - `NULL` for no minor breaks +#' - `waiver()` for the default breaks (one minor break between +#' each major break) +#' - A numeric vector of positions +#' - A function that given the limits returns a vector of minor breaks. +#' @param labels One of: +#' - `NULL` for no labels +#' - `waiver()` for the default labels computed by the +#' transformation object +#' - A character vector giving labels (must be same length as `breaks`) +#' - A function that takes the breaks as input and returns labels +#' as output +#' @param limits One of: +#' - `NULL` to use the default scale range +#' - A numeric vector of length two providing limits of the scale. +#' Use `NA` to refer to the existing minimum or maximum +#' - A function that accepts the existing (automatic) limits and returns +#' new limits +#' @param rescaler A function used to scale the input values to the +#' range \[0, 1]. This is always [scales::rescale()], except for +#' diverging and n colour gradients (i.e., [scale_colour_gradient2()], +#' [scale_colour_gradientn()]). The `rescaler` is ignored by position +#' scales, which ways use [scales::rescale()]. +#' @param oob Function that handles limits outside of the scale limits +#' (out of bounds). The default ([scales::censor()]) replaces out of +#' bounds values with `NA`. +#' @param na.value Missing values will be replaced with this value. +#' @param trans For continuous scales, the name of a transformation object +#' or the object itself. Built-in transformations include "asn", "atanh", +#' "boxcox", "date", "exp", "hms", "identity", "log", "log10", "log1p", "log2", +#' "logit", "modulus", "probability", "probit", "pseudo_log", "reciprocal", +#' "reverse", "sqrt" and "time". +#' +#' A transformation object bundles together a transform, its inverse, +#' and methods for generating breaks and labels. Transformation objects +#' are defined in the scales package, and are called `_trans` (e.g., +#' [scales::boxcox_trans()]). You can create your own +#' transformation with [scales::trans_new()]. +#' @param guide A function used to create a guide or its name. See +#' [guides()] for more information. +#' @param expand For position scales, a vector of range expansion constants used to add some +#' padding around the data to ensure that they are placed some distance +#' away from the axes. Use the convenience function [expand_scale()] +#' to generate the values for the `expand` argument. The defaults are to +#' expand the scale by 5\% on each side for continuous variables, and by +#' 0.6 units on each side for discrete variables. +#' @param position For position scales, The position of the axis. +#' `left` or `right` for y axes, `top` or `bottom` for x axes. +#' @param super The super class to use for the constructed scale +#' @keywords internal +continuous_scale <- function(aesthetics, scale_name, palette, name = waiver(), + breaks = waiver(), minor_breaks = waiver(), labels = waiver(), limits = NULL, + rescaler = rescale, oob = censor, expand = waiver(), na.value = NA_real_, + trans = "identity", guide = "legend", position = "left", super = ScaleContinuous) { + + aesthetics <- standardise_aes_names(aesthetics) + + check_breaks_labels(breaks, labels) + + position <- match.arg(position, c("left", "right", "top", "bottom")) + + # If the scale is non-positional, break = NULL means removing the guide + if (is.null(breaks) && all(!is_position_aes(aesthetics))) { + guide <- "none" + } + + trans <- as.trans(trans) + if (!is.null(limits) && !is.function(limits)) { + limits <- trans$transform(limits) + } + + ggproto(NULL, super, + call = match.call(), + + aesthetics = aesthetics, + scale_name = scale_name, + palette = palette, + + range = continuous_range(), + limits = limits, + trans = trans, + na.value = na.value, + expand = expand, + rescaler = rescaler, + oob = oob, + + name = name, + breaks = breaks, + minor_breaks = minor_breaks, + + labels = labels, + guide = guide, + position = position + ) +} + +#' Discrete scale constructor +#' +#' @export +#' @inheritParams continuous_scale +#' @param palette A palette function that when called with a single integer +#' argument (the number of levels in the scale) returns the values that +#' they should take (e.g., [scales::hue_pal()]). +#' @param breaks One of: +#' - `NULL` for no breaks +#' - `waiver()` for the default breaks (the scale limits) +#' - A character vector of breaks +#' - A function that takes the limits as input and returns breaks +#' as output +#' @param limits A character vector that defines possible values of the scale +#' and their order. +#' @param drop Should unused factor levels be omitted from the scale? +#' The default, `TRUE`, uses the levels that appear in the data; +#' `FALSE` uses all the levels in the factor. +#' @param na.translate Unlike continuous scales, discrete scales can easily show +#' missing values, and do so by default. If you want to remove missing values +#' from a discrete scale, specify `na.translate = FALSE`. +#' @param na.value If `na.translate = TRUE`, what value aesthetic +#' value should missing be displayed as? Does not apply to position scales +#' where `NA` is always placed at the far right. +#' @keywords internal +discrete_scale <- function(aesthetics, scale_name, palette, name = waiver(), + breaks = waiver(), labels = waiver(), limits = NULL, expand = waiver(), + na.translate = TRUE, na.value = NA, drop = TRUE, + guide = "legend", position = "left", super = ScaleDiscrete) { + + aesthetics <- standardise_aes_names(aesthetics) + + check_breaks_labels(breaks, labels) + + position <- match.arg(position, c("left", "right", "top", "bottom")) + + # If the scale is non-positional, break = NULL means removing the guide + if (is.null(breaks) && all(!is_position_aes(aesthetics))) { + guide <- "none" + } + + ggproto(NULL, super, + call = match.call(), + + aesthetics = aesthetics, + scale_name = scale_name, + palette = palette, + + range = discrete_range(), + limits = limits, + na.value = na.value, + na.translate = na.translate, + expand = expand, + + name = name, + breaks = breaks, + labels = labels, + drop = drop, + guide = guide, + position = position + ) +} + #' @section Scales: #' -#' All `scale_*` functions (like `scale_x_continuous`) return a -#' `Scale*` object (like `ScaleContinuous`). The `Scale*` -#' object represents a single scale. +#' All `scale_*` functions like [scale_x_continuous()] return a `Scale*` +#' object like `ScaleContinuous`. Each of the `Scale*` objects is a [ggproto()] +#' object, descended from the top-level `Scale`. +#' +#' Properties not documented in [continuous_scale()] or [discrete_scale()]: +#' +#' - `call` The call to [continuous_scale()] or [discrete_scale()] that constructed +#' the scale. +#' +#' - `range` One of `continuous_range()` or `discrete_range()`. +#' +#' +#' Methods: +#' +#' - `is_discrete()` Returns `TRUE` if the scale is a discrete scale +#' +#' - `is_empty()` Returns `TRUE` if the scale contains no information (i.e., +#' it has no information with which to calculate its `limits`). +#' +#' - `clone()` Returns a copy of the scale that can be trained +#' independently without affecting the original scale. +#' +#' - `transform()` Transforms a vector of values using `self$trans`. +#' This occurs before the `Stat` is calculated. +#' +#' - `train()` Update the `self$range` of observed (transformed) data values with +#' a vector of (possibly) new values. +#' +#' - `reset()` Reset the `self$range` of observed data values. For discrete +#' position scales, only the continuous range is reset. +#' +#' - `map()` Map transformed data values to some output value as +#' determined by `self$rescale()` and `self$pallete` (except for position scales, +#' which do not use the default implementation of this method). The output corresponds +#' to the transformed data value in aesthetic space (e.g., a color, line width, or size). +#' +#' - `rescale()` Rescale transformed data to the the range 0, 1. This is most useful for +#' position scales. For continuous scales, `rescale()` uses the `rescaler` that +#' was provided to the constructor. `rescale()` does not apply `self$oob()` to +#' its input, which means that discrete values outside `limits` will be `NA`, and +#' values that are outside `range` will have values less than 0 or greater than 1. +#' This allows guides more control over how out-of-bounds values are displayed. +#' +#' - `transform_df()`, `train_df()`, `map_df()` These `_df` variants +#' accept a data frame, and apply the `transform`, `train`, and `map` methods +#' (respectively) to the columns whose names are in `self$aesthetics`. +#' +#' - `get_limits()` Calculates the final scale limits in transformed data space +#' based on the combination of `self$limits` and/or the range of observed values +#' (`self$range`). +#' +#' - `get_breaks()` Calculates the final scale breaks in transformed data space +#' based on on the combination of `self$breaks`, `self$trans$breaks()` (for +#' continuous scales), and `limits`. Breaks outside of `limits` are assigned +#' a value of `NA` (continuous scales) or dropped (discrete scales). +#' +#' - `get_labels()` Calculates labels for a given set of (transformed) `breaks` +#' based on the combination of `self$labels` and `breaks`. +#' +#' - `get_breaks_minor()` For continuous scales, calculates the final scale minor breaks +#' in transformed data space based on the rescaled `breaks`, the value of `self$minor_breaks`, +#' and the value of `self$trans$minor_breaks()`. Discrete scales always return `NULL`. +#' +#' - `make_title()` Hook to modify the title that is calculated during guide construction +#' (for non-position scales) or when the `Layout` calculates the x and y labels +#' (position scales). +#' +#' These methods are only valid for position (x and y) scales: #' -#' Each of the `Scale*` objects is a [ggproto()] object, -#' descended from the top-level `Scale`. +#' - `dimension()` For continuous scales, the dimension is the same concept as the limits. +#' For discrete scales, `dimension()` returns a continuous range, where the limits +#' would be placed at integer positions. `dimension()` optionally expands +#' this range given an expantion of length 4 (see [expand_scale()]). +#' +#' - `break_info()` Returns a `list()` with calculated values needed for the `Coord` +#' to transform values in transformed data space. Axis and grid guides also use +#' these values to draw guides. This is called with +#' a (usually expanded) continuous range, such as that returned by `self$dimension()` +#' (even for discrete scales). The list has components `major_source` +#' (`self$get_breaks()` for continuous scales, or `seq_along(self$get_breaks())` +#' for discrete scales), `major` (the rescaled value of `major_source`, ignoring +#' `self$rescaler`), `minor` (the rescaled value of `minor_source`, ignoring +#' `self$rescaler`), `range` (the range that was passed in to `break_info()`), +#' `labels` (the label values, one for each element in `breaks`). +#' +#' - `axis_order()` One of `c("primary", "secondary")` or `c("secondary", "primary")` +#' +#' - `make_sec_title()` Hook to modify the title for the second axis that is calculated +#' when the `Layout` calculates the x and y labels. #' #' @rdname ggplot2-ggproto #' @format NULL @@ -36,10 +300,6 @@ Scale <- ggproto("Scale", NULL, stop("Not implemented", call. = FALSE) }, - # Train scale from a data frame. - # - # @return updated range (invisibly) - # @seealso [scale_train()] for scale specific generic method train_df = function(self, df) { if (empty(df)) return() @@ -50,12 +310,10 @@ Scale <- ggproto("Scale", NULL, invisible() }, - # Train an individual scale from a vector of data. train = function(self, x) { stop("Not implemented", call. = FALSE) }, - # Reset scale, untraining ranges reset = function(self) { self$range$reset() }, @@ -64,12 +322,15 @@ Scale <- ggproto("Scale", NULL, is.null(self$range$range) && is.null(self$limits) }, - # @return list of transformed variables transform_df = function(self, df) { - if (empty(df)) return() + if (empty(df)) { + return() + } aesthetics <- intersect(self$aesthetics, names(df)) - if (length(aesthetics) == 0) return() + if (length(aesthetics) == 0) { + return() + } lapply(df[aesthetics], self$transform) }, @@ -78,13 +339,16 @@ Scale <- ggproto("Scale", NULL, stop("Not implemented", call. = FALSE) }, - # @return list of mapped variables map_df = function(self, df, i = NULL) { - if (empty(df)) return() + if (empty(df)) { + return() + } aesthetics <- intersect(self$aesthetics, names(df)) names(aesthetics) <- aesthetics - if (length(aesthetics) == 0) return() + if (length(aesthetics) == 0) { + return() + } if (is.null(i)) { lapply(aesthetics, function(j) self$map(df[[j]])) @@ -93,25 +357,18 @@ Scale <- ggproto("Scale", NULL, } }, - # @kohske - # map tentatively accept limits argument. - # map replaces oob (i.e., outside limits) values with NA. - # - # Previously limits are always scale_limits(scale). - # But if this function is called to get breaks, - # and breaks spans oob, the oob breaks is replaces by NA. - # This makes impossible to display oob breaks. - # Now coord_train calls this function with limits determined by coord (with expansion). map = function(self, x, limits = self$get_limits()) { stop("Not implemented", call. = FALSE) }, - # if scale is a function, apply it to the default (inverted) scale range - # if scale is NULL, use the default scale range - # if scale contains a NA, use the default range for that axis, otherwise - # use the user defined limit for that axis + rescale = function(self, x, limits = self$get_limits(), range = self$dimension()) { + stop("Not implemented", call. = FALSE) + }, + get_limits = function(self) { - if (self$is_empty()) return(c(0, 1)) + if (self$is_empty()) { + return(c(0, 1)) + } if (is.null(self$limits)) { self$range$range @@ -123,10 +380,7 @@ Scale <- ggproto("Scale", NULL, } }, - # The physical size of the scale. - # This always returns a numeric vector of length 4, giving the physical - # dimensions of a scale. - dimension = function(self, expand = c(0, 0, 0, 0)) { + dimension = function(self, expand = c(0, 0, 0, 0), limits = self$get_limits()) { stop("Not implemented", call. = FALSE) }, @@ -134,7 +388,6 @@ Scale <- ggproto("Scale", NULL, stop("Not implemented", call. = FALSE) }, - # The numeric position of scale breaks, used by coord/guide break_positions = function(self, range = self$get_limits()) { self$map(self$get_breaks(range)) }, @@ -147,8 +400,6 @@ Scale <- ggproto("Scale", NULL, stop("Not implemented", call. = FALSE) }, - # Each implementation of a Scale must implement a clone method that makes - # copies of reference objecsts. clone = function(self) { stop("Not implemented", call. = FALSE) }, @@ -157,7 +408,6 @@ Scale <- ggproto("Scale", NULL, stop("Not implemented", call. = FALSE) }, - # Only relevant for positional scales axis_order = function(self) { ord <- c("primary", "secondary") if (self$position %in% c("right", "bottom")) { @@ -166,18 +416,22 @@ Scale <- ggproto("Scale", NULL, ord }, - # Here to make it possible for scales to modify the default titles make_title = function(title) { title }, + make_sec_title = function(title) { title } ) check_breaks_labels <- function(breaks, labels) { - if (is.null(breaks)) return(TRUE) - if (is.null(labels)) return(TRUE) + if (is.null(breaks)) { + return(TRUE) + } + if (is.null(labels)) { + return(TRUE) + } bad_labels <- is.atomic(breaks) && is.atomic(labels) && length(breaks) != length(labels) @@ -196,14 +450,16 @@ check_breaks_labels <- function(breaks, labels) { ScaleContinuous <- ggproto("ScaleContinuous", Scale, range = continuous_range(), na.value = NA_real_, - rescaler = rescale, # Used by diverging and n colour gradients x + rescaler = rescale, oob = censor, minor_breaks = waiver(), is_discrete = function() FALSE, train = function(self, x) { - if (length(x) == 0) return() + if (length(x) == 0) { + return() + } self$range$train(x) }, @@ -218,7 +474,7 @@ ScaleContinuous <- ggproto("ScaleContinuous", Scale, }, map = function(self, x, limits = self$get_limits()) { - x <- self$rescaler(self$oob(x, range = limits), from = limits) + x <- self$rescale(self$oob(x, range = limits), limits) uniq <- unique(x) pal <- self$palette(uniq) @@ -227,21 +483,31 @@ ScaleContinuous <- ggproto("ScaleContinuous", Scale, ifelse(!is.na(scaled), scaled, self$na.value) }, - dimension = function(self, expand = c(0, 0, 0, 0)) { - expand_range4(self$get_limits(), expand) + rescale = function(self, x, limits = self$get_limits(), range = limits) { + self$rescaler(x, from = range) + }, + + dimension = function(self, expand = c(0, 0, 0, 0), limits = self$get_limits()) { + expand_range4(limits, expand) }, get_breaks = function(self, limits = self$get_limits()) { - if (self$is_empty()) return(numeric()) + if (self$is_empty()) { + return(numeric()) + } # Limits in transformed space need to be converted back to data space limits <- self$trans$inverse(limits) if (is.null(self$breaks)) { return(NULL) - } else if (identical(self$breaks, NA)) { - stop("Invalid breaks specification. Use NULL, not NA") - } else if (zero_range(as.numeric(limits))) { + } + + if (identical(self$breaks, NA)) { + stop("Invalid breaks specification. Use NULL, not NA", call. = FALSE) + } + + if (zero_range(as.numeric(limits))) { breaks <- limits[1] } else if (is.waive(self$breaks)) { breaks <- self$trans$breaks(limits) @@ -252,13 +518,10 @@ ScaleContinuous <- ggproto("ScaleContinuous", Scale, } # Breaks in data space need to be converted back to transformed space - # And any breaks outside the dimensions need to be flagged as missing - # - # @kohske - # TODO: replace NA with something else for flag. - # guides cannot discriminate oob from missing value. - breaks <- censor(self$trans$transform(breaks), self$trans$transform(limits), - only.finite = FALSE) + breaks <- self$trans$transform(breaks) + # Any breaks outside the dimensions are flagged as missing + breaks <- censor(breaks, self$trans$transform(limits), only.finite = FALSE) + breaks }, @@ -269,9 +532,13 @@ ScaleContinuous <- ggproto("ScaleContinuous", Scale, if (is.null(self$minor_breaks)) { return(NULL) - } else if (identical(self$minor_breaks, NA)) { + } + + if (identical(self$minor_breaks, NA)) { stop("Invalid minor_breaks specification. Use NULL, not NA", call. = FALSE) - } else if (is.waive(self$minor_breaks)) { + } + + if (is.waive(self$minor_breaks)) { if (is.null(b)) { breaks <- NULL } else { @@ -290,24 +557,32 @@ ScaleContinuous <- ggproto("ScaleContinuous", Scale, }, get_labels = function(self, breaks = self$get_breaks()) { - if (is.null(breaks)) return(NULL) + if (is.null(breaks)) { + return(NULL) + } breaks <- self$trans$inverse(breaks) if (is.null(self$labels)) { return(NULL) - } else if (identical(self$labels, NA)) { + } + + if (identical(self$labels, NA)) { stop("Invalid labels specification. Use NULL, not NA", call. = FALSE) - } else if (is.waive(self$labels)) { + } + + if (is.waive(self$labels)) { labels <- self$trans$format(breaks) } else if (is.function(self$labels)) { labels <- self$labels(breaks) } else { labels <- self$labels } + if (length(labels) != length(breaks)) { - stop("Breaks and labels are different lengths") + stop("Breaks and labels are different lengths", call. = FALSE) } + labels }, @@ -339,9 +614,14 @@ ScaleContinuous <- ggproto("ScaleContinuous", Scale, major_n <- rescale(major, from = range) minor_n <- rescale(minor, from = range) - list(range = range, labels = labels, - major = major_n, minor = minor_n, - major_source = major, minor_source = minor) + list( + range = range, + labels = labels, + major = major_n, + minor = minor_n, + major_source = major, + minor_source = minor + ) }, print = function(self, ...) { @@ -367,7 +647,9 @@ ScaleDiscrete <- ggproto("ScaleDiscrete", Scale, is_discrete = function() TRUE, train = function(self, x) { - if (length(x) == 0) return() + if (length(x) == 0) { + return() + } self$range$train(x, drop = self$drop, na.rm = !self$na.translate) }, @@ -380,7 +662,9 @@ ScaleDiscrete <- ggproto("ScaleDiscrete", Scale, if (!is.null(self$n.breaks.cache) && self$n.breaks.cache == n) { pal <- self$palette.cache } else { - if (!is.null(self$n.breaks.cache)) warning("Cached palette does not match requested", call. = FALSE) + if (!is.null(self$n.breaks.cache)) { + warning("Cached palette does not match requested", call. = FALSE) + } pal <- self$palette(n) self$palette.cache <- pal self$n.breaks.cache <- n @@ -400,18 +684,28 @@ ScaleDiscrete <- ggproto("ScaleDiscrete", Scale, } }, - dimension = function(self, expand = c(0, 0, 0, 0)) { - expand_range4(length(self$get_limits()), expand) + rescale = function(self, x, limits = self$get_limits(), range = c(1, length(limits))) { + rescale(x, match(as.character(x), limits), from = range) + }, + + dimension = function(self, expand = c(0, 0, 0, 0), limits = self$get_limits()) { + expand_range4(c(1, length(limits)), expand) }, get_breaks = function(self, limits = self$get_limits()) { - if (self$is_empty()) return(numeric()) + if (self$is_empty()) { + return(numeric()) + } if (is.null(self$breaks)) { return(NULL) - } else if (identical(self$breaks, NA)) { + } + + if (identical(self$breaks, NA)) { stop("Invalid breaks specification. Use NULL, not NA", call. = FALSE) - } else if (is.waive(self$breaks)) { + } + + if (is.waive(self$breaks)) { breaks <- limits } else if (is.function(self$breaks)) { breaks <- self$breaks(limits) @@ -419,23 +713,31 @@ ScaleDiscrete <- ggproto("ScaleDiscrete", Scale, breaks <- self$breaks } - # Breaks can only occur only on values in domain - in_domain <- intersect(breaks, self$get_limits()) + # Breaks only occur only on values in domain + in_domain <- intersect(breaks, limits) structure(in_domain, pos = match(in_domain, breaks)) }, get_breaks_minor = function(...) NULL, get_labels = function(self, breaks = self$get_breaks()) { - if (self$is_empty()) return(character()) + if (self$is_empty()) { + return(character()) + } - if (is.null(breaks)) return(NULL) + if (is.null(breaks)) { + return(NULL) + } if (is.null(self$labels)) { return(NULL) - } else if (identical(self$labels, NA)) { + } + + if (identical(self$labels, NA)) { stop("Invalid labels specification. Use NULL, not NA", call. = FALSE) - } else if (is.waive(self$labels)) { + } + + if (is.waive(self$labels)) { breaks <- self$get_breaks() if (is.numeric(breaks)) { # Only format numbers, because on Windows, format messes up encoding @@ -490,185 +792,17 @@ ScaleDiscrete <- ggproto("ScaleDiscrete", Scale, major_n <- rescale(major, from = range) } - list(range = range, labels = labels, - major = major_n, minor = NULL, - major_source = major, minor_source = NULL) + list( + range = range, + labels = labels, + major = major_n, + minor = NULL, + major_source = major, + minor_source = NULL + ) } ) - -#' Continuous scale constructor. -#' -#' @export -#' @param aesthetics The names of the aesthetics that this scale works with -#' @param scale_name The name of the scale -#' @param palette A palette function that when called with a numeric vector with -#' values between 0 and 1 returns the corresponding values in the range the -#' scale maps to. -#' @param name The name of the scale. Used as the axis or legend title. If -#' `waiver()`, the default, the name of the scale is taken from the first -#' mapping used for that aesthetic. If `NULL`, the legend title will be -#' omitted. -#' @param breaks One of: -#' - `NULL` for no breaks -#' - `waiver()` for the default breaks computed by the -#' transformation object -#' - A numeric vector of positions -#' - A function that takes the limits as input and returns breaks -#' as output -#' @param minor_breaks One of: -#' - `NULL` for no minor breaks -#' - `waiver()` for the default breaks (one minor break between -#' each major break) -#' - A numeric vector of positions -#' - A function that given the limits returns a vector of minor breaks. -#' @param labels One of: -#' - `NULL` for no labels -#' - `waiver()` for the default labels computed by the -#' transformation object -#' - A character vector giving labels (must be same length as `breaks`) -#' - A function that takes the breaks as input and returns labels -#' as output -#' @param limits One of: -#' - `NULL` to use the default scale range -#' - A numeric vector of length two providing limits of the scale. -#' Use `NA` to refer to the existing minimum or maximum -#' - A function that accepts the existing (automatic) limits and returns -#' new limits -#' @param rescaler Used by diverging and n colour gradients -#' (i.e. [scale_colour_gradient2()], [scale_colour_gradientn()]). -#' A function used to scale the input values to the range \[0, 1]. -#' @param oob Function that handles limits outside of the scale limits -#' (out of bounds). The default replaces out of bounds values with `NA`. -#' @inheritParams scale_x_discrete -#' @param na.value Missing values will be replaced with this value. -#' @param trans Either the name of a transformation object, or the -#' object itself. Built-in transformations include "asn", "atanh", -#' "boxcox", "date", "exp", "hms", "identity", "log", "log10", "log1p", "log2", -#' "logit", "modulus", "probability", "probit", "pseudo_log", "reciprocal", -#' "reverse", "sqrt" and "time". -#' -#' A transformation object bundles together a transform, its inverse, -#' and methods for generating breaks and labels. Transformation objects -#' are defined in the scales package, and are called `name_trans`, e.g. -#' [scales::boxcox_trans()]. You can create your own -#' transformation with [scales::trans_new()]. -#' @param guide A function used to create a guide or its name. See -#' [guides()] for more info. -#' @param position The position of the axis. "left" or "right" for vertical -#' scales, "top" or "bottom" for horizontal scales -#' @param super The super class to use for the constructed scale -#' @keywords internal -continuous_scale <- function(aesthetics, scale_name, palette, name = waiver(), - breaks = waiver(), minor_breaks = waiver(), labels = waiver(), limits = NULL, - rescaler = rescale, oob = censor, expand = waiver(), na.value = NA_real_, - trans = "identity", guide = "legend", position = "left", super = ScaleContinuous) { - - aesthetics <- standardise_aes_names(aesthetics) - - check_breaks_labels(breaks, labels) - - position <- match.arg(position, c("left", "right", "top", "bottom")) - - # If the scale is non-positional, break = NULL means removing the guide - if (is.null(breaks) && all(!is_position_aes(aesthetics))) { - guide <- "none" - } - - trans <- as.trans(trans) - if (!is.null(limits) && !is.function(limits)) { - limits <- trans$transform(limits) - } - - ggproto(NULL, super, - call = match.call(), - - aesthetics = aesthetics, - scale_name = scale_name, - palette = palette, - - range = continuous_range(), - limits = limits, - trans = trans, - na.value = na.value, - expand = expand, - rescaler = rescaler, # Used by diverging and n colour gradients - oob = oob, - - name = name, - breaks = breaks, - minor_breaks = minor_breaks, - - labels = labels, - guide = guide, - position = position - ) -} - -#' Discrete scale constructor. -#' -#' @export -#' @inheritParams continuous_scale -#' @param palette A palette function that when called with a single integer -#' argument (the number of levels in the scale) returns the values that -#' they should take. -#' @param breaks One of: -#' - `NULL` for no breaks -#' - `waiver()` for the default breaks computed by the -#' transformation object -#' - A character vector of breaks -#' - A function that takes the limits as input and returns breaks -#' as output -#' @param limits A character vector that defines possible values of the scale -#' and their order. -#' @param drop Should unused factor levels be omitted from the scale? -#' The default, `TRUE`, uses the levels that appear in the data; -#' `FALSE` uses all the levels in the factor. -#' @param na.translate Unlike continuous scales, discrete scales can easily show -#' missing values, and do so by default. If you want to remove missing values -#' from a discrete scale, specify `na.translate = FALSE`. -#' @param na.value If `na.translate = TRUE`, what value aesthetic -#' value should missing be displayed as? Does not apply to position scales -#' where `NA` is always placed at the far right. -#' @keywords internal -discrete_scale <- function(aesthetics, scale_name, palette, name = waiver(), - breaks = waiver(), labels = waiver(), limits = NULL, expand = waiver(), - na.translate = TRUE, na.value = NA, drop = TRUE, - guide = "legend", position = "left", super = ScaleDiscrete) { - - aesthetics <- standardise_aes_names(aesthetics) - - check_breaks_labels(breaks, labels) - - position <- match.arg(position, c("left", "right", "top", "bottom")) - - # If the scale is non-positional, break = NULL means removing the guide - if (is.null(breaks) && all(!is_position_aes(aesthetics))) { - guide <- "none" - } - - ggproto(NULL, super, - call = match.call(), - - aesthetics = aesthetics, - scale_name = scale_name, - palette = palette, - - range = discrete_range(), - limits = limits, - na.value = na.value, - na.translate = na.translate, - expand = expand, - - name = name, - breaks = breaks, - labels = labels, - drop = drop, - guide = guide, - position = position - ) -} - # In place modification of a scale to change the primary axis scale_flip_position <- function(scale) { scale$position <- switch(scale$position, diff --git a/R/scale-discrete-.r b/R/scale-discrete-.r index 7d1d5999b3..13c04be751 100644 --- a/R/scale-discrete-.r +++ b/R/scale-discrete-.r @@ -6,15 +6,8 @@ #' level, and increasing by one for each level (i.e. the labels are placed #' at integer positions). This is what allows jittering to work. #' -#' @inheritDotParams discrete_scale -expand -position -#' @param expand Vector of range expansion constants used to add some -#' padding around the data, to ensure that they are placed some distance -#' away from the axes. Use the convenience function [expand_scale()] -#' to generate the values for the `expand` argument. The defaults are to -#' expand the scale by 5\% on each side for continuous variables, and by -#' 0.6 units on each side for discrete variables. -#' @param position The position of the axis. `left` or `right` for y -#' axes, `top` or `bottom` for x axes +#' @inheritDotParams discrete_scale +#' @inheritParams discrete_scale #' @rdname scale_discrete #' @family position scales #' @export @@ -96,7 +89,7 @@ ScaleDiscretePosition <- ggproto("ScaleDiscretePosition", ScaleDiscrete, }, reset = function(self) { - # Can't reset discrete scale because no way to recover values + # Can't reset discrete position scale because no way to recover values self$range_c$reset() }, @@ -108,9 +101,13 @@ ScaleDiscretePosition <- ggproto("ScaleDiscretePosition", ScaleDiscrete, } }, - dimension = function(self, expand = c(0, 0, 0, 0)) { + rescale = function(self, x, limits = self$get_limits(), range = self$dimension(limits = limits)) { + rescale(self$map(x, limits = limits), from = range) + }, + + dimension = function(self, expand = c(0, 0, 0, 0), limits = self$get_limits()) { c_range <- self$range_c$range - d_range <- self$get_limits() + d_range <- limits if (self$is_empty()) { c(0, 1) @@ -126,10 +123,6 @@ ScaleDiscretePosition <- ggproto("ScaleDiscretePosition", ScaleDiscrete, } }, - get_breaks = function(self, limits = self$get_limits()) { - ggproto_parent(ScaleDiscrete, self)$get_breaks(limits) - }, - clone = function(self) { new <- ggproto(NULL, self) new$range <- discrete_range() diff --git a/R/scale-view.r b/R/scale-view.r new file mode 100644 index 0000000000..13afdba516 --- /dev/null +++ b/R/scale-view.r @@ -0,0 +1,128 @@ + +#' View scale constructor +#' +#' View scales are an implementation of `Scale` objects that have fixed +#' limits, dimension, breaks, labels, and minor breaks. They are used as +#' the immutable result of the trained scales that have been assigned +#' `limits` and a `continuous_range` from the coordinate system's +#' implementation of scale expantion. +#' +#' @param scale The scale from which to construct a view scale. +#' @param limits The final scale limits +#' @param continuous_range The final dimensions of the scale +#' +#' @noRd +view_scale_primary <- function(scale, limits = scale$get_limits(), + continuous_range = scale$dimension(limits = limits)) { + + if(!scale$is_discrete()) { + breaks <- scale$get_breaks(continuous_range) + breaks <- breaks[is.finite(breaks)] + minor_breaks <- scale$get_breaks_minor(b = breaks, limits = continuous_range) + } else { + breaks <- scale$get_breaks(limits) + minor_breaks <- scale$get_breaks_minor(b = breaks, limits = limits) + } + + ggproto(NULL, ViewScale, + scale = scale, + aesthetics = scale$aesthetics, + name = scale$name, + scale_is_discrete = scale$is_discrete(), + limits = limits, + continuous_range = continuous_range, + breaks = breaks, + labels = scale$get_labels(breaks), + minor_breaks = minor_breaks + ) +} + +# this function is a hack that is difficult to avoid given the complex implementation of second axes +view_scale_secondary <- function(scale, limits = scale$get_limits(), + continuous_range = scale$dimension(limits = limits)) { + if (is.null(scale$secondary.axis) || is.waive(scale$secondary.axis) || scale$secondary.axis$empty()) { + view_scale_empty() + } else { + scale$secondary.axis$init(scale) + break_info <- scale$secondary.axis$break_info(continuous_range, scale) + names(break_info) <- gsub("sec\\.", "", names(break_info)) + + ggproto(NULL, ViewScale, + scale = scale, + break_info = break_info, + aesthetics = paste0(scale$aesthetics, ".sec"), + name = scale$sec_name(), + make_title = function(self, title) self$scale$make_sec_title(title), + + dimension = function(self) self$break_info$range, + get_limits = function(self) self$break_info$range, + get_breaks = function(self) self$break_info$major_source, + get_breaks_minor = function(self) self$break_info$minor_source, + break_positions = function(self) self$break_info$major, + break_positions_minor = function(self) self$break_info$minor, + get_labels = function(self) self$break_info$labels, + rescale = function(x) rescale(x, from = break_info$range, to = c(0, 1)) + ) + } +} + +view_scale_empty <- function() { + ggproto(NULL, ViewScale, + is_empty = function() TRUE, + is_discrete = function() NA, + dimension = function() c(0, 1), + get_limits = function() c(0, 1), + get_breaks = function() NULL, + get_breaks_minor = function() NULL, + get_labels = function() NULL, + rescale = function(x) stop("Not implemented", call. = FALSE), + map = function(x) stop("Not implemented", call. = FALSE), + make_title = function(title) title, + break_positions = function() NULL, + break_positions_minor = function() NULL + ) +} + +ViewScale <- ggproto("ViewScale", NULL, + # map, rescale, and make_title need a reference + # to the original scale + scale = ggproto(NULL, Scale), + aesthetics = NULL, + name = waiver(), + scale_is_discrete = FALSE, + limits = NULL, + continuous_range = NULL, + breaks = NULL, + labels = NULL, + minor_breaks = NULL, + + is_empty = function(self) { + is.null(self$get_breaks()) && is.null(self$get_breaks_minor()) + }, + is_discrete = function(self) self$scale_is_discrete, + dimension = function(self) self$continuous_range, + get_limits = function(self) self$limits, + get_breaks = function(self) self$breaks, + get_breaks_minor = function(self) self$minor_breaks, + get_labels = function(self) self$labels, + rescale = function(self, x) { + self$scale$rescale(x, self$limits, self$continuous_range) + }, + map = function(self, x) { + self$scale$map(x, self$limits) + }, + make_title = function(self, title) { + self$scale$make_title(title) + }, + break_positions = function(self) { + self$rescale(self$get_breaks()) + }, + break_positions_minor = function(self) { + b <- self$get_breaks_minor() + if (is.null(b)) { + return(NULL) + } + + self$rescale(b) + } +) diff --git a/man/continuous_scale.Rd b/man/continuous_scale.Rd index 36d46fb5af..754fd16fe8 100644 --- a/man/continuous_scale.Rd +++ b/man/continuous_scale.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/scale-.r \name{continuous_scale} \alias{continuous_scale} -\title{Continuous scale constructor.} +\title{Continuous scale constructor} \usage{ continuous_scale(aesthetics, scale_name, palette, name = waiver(), breaks = waiver(), minor_breaks = waiver(), labels = waiver(), @@ -11,13 +11,14 @@ continuous_scale(aesthetics, scale_name, palette, name = waiver(), guide = "legend", position = "left", super = ScaleContinuous) } \arguments{ -\item{aesthetics}{The names of the aesthetics that this scale works with} +\item{aesthetics}{The names of the aesthetics that this scale works with.} -\item{scale_name}{The name of the scale} +\item{scale_name}{The name of the scale that should be used for error messages +associated with this scale.} \item{palette}{A palette function that when called with a numeric vector with -values between 0 and 1 returns the corresponding values in the range the -scale maps to.} +values between 0 and 1 returns the corresponding output values +(e.g., \code{\link[scales:area_pal]{scales::area_pal()}}).} \item{name}{The name of the scale. Used as the axis or legend title. If \code{waiver()}, the default, the name of the scale is taken from the first @@ -28,10 +29,10 @@ omitted.} \itemize{ \item \code{NULL} for no breaks \item \code{waiver()} for the default breaks computed by the -transformation object +\link[scales:trans_new]{transformation object} \item A numeric vector of positions \item A function that takes the limits as input and returns breaks -as output +as output (e.g., a function returned by \code{\link[scales:extended_breaks]{scales::extended_breaks()}}) }} \item{minor_breaks}{One of: @@ -62,15 +63,18 @@ Use \code{NA} to refer to the existing minimum or maximum new limits }} -\item{rescaler}{Used by diverging and n colour gradients -(i.e. \code{\link[=scale_colour_gradient2]{scale_colour_gradient2()}}, \code{\link[=scale_colour_gradientn]{scale_colour_gradientn()}}). -A function used to scale the input values to the range [0, 1].} +\item{rescaler}{A function used to scale the input values to the +range [0, 1]. This is always \code{\link[scales:rescale]{scales::rescale()}}, except for +diverging and n colour gradients (i.e., \code{\link[=scale_colour_gradient2]{scale_colour_gradient2()}}, +\code{\link[=scale_colour_gradientn]{scale_colour_gradientn()}}). The \code{rescaler} is ignored by position +scales, which ways use \code{\link[scales:rescale]{scales::rescale()}}.} \item{oob}{Function that handles limits outside of the scale limits -(out of bounds). The default replaces out of bounds values with \code{NA}.} +(out of bounds). The default (\code{\link[scales:censor]{scales::censor()}}) replaces out of +bounds values with \code{NA}.} -\item{expand}{Vector of range expansion constants used to add some -padding around the data, to ensure that they are placed some distance +\item{expand}{For position scales, a vector of range expansion constants used to add some +padding around the data to ensure that they are placed some distance away from the axes. Use the convenience function \code{\link[=expand_scale]{expand_scale()}} to generate the values for the \code{expand} argument. The defaults are to expand the scale by 5\% on each side for continuous variables, and by @@ -78,27 +82,27 @@ expand the scale by 5\% on each side for continuous variables, and by \item{na.value}{Missing values will be replaced with this value.} -\item{trans}{Either the name of a transformation object, or the -object itself. Built-in transformations include "asn", "atanh", +\item{trans}{For continuous scales, the name of a transformation object +or the object itself. Built-in transformations include "asn", "atanh", "boxcox", "date", "exp", "hms", "identity", "log", "log10", "log1p", "log2", "logit", "modulus", "probability", "probit", "pseudo_log", "reciprocal", "reverse", "sqrt" and "time". A transformation object bundles together a transform, its inverse, and methods for generating breaks and labels. Transformation objects -are defined in the scales package, and are called \code{name_trans}, e.g. -\code{\link[scales:boxcox_trans]{scales::boxcox_trans()}}. You can create your own +are defined in the scales package, and are called \code{_trans} (e.g., +\code{\link[scales:boxcox_trans]{scales::boxcox_trans()}}). You can create your own transformation with \code{\link[scales:trans_new]{scales::trans_new()}}.} \item{guide}{A function used to create a guide or its name. See -\code{\link[=guides]{guides()}} for more info.} +\code{\link[=guides]{guides()}} for more information.} -\item{position}{The position of the axis. "left" or "right" for vertical -scales, "top" or "bottom" for horizontal scales} +\item{position}{For position scales, The position of the axis. +\code{left} or \code{right} for y axes, \code{top} or \code{bottom} for x axes.} \item{super}{The super class to use for the constructed scale} } \description{ -Continuous scale constructor. +Continuous scale constructor } \keyword{internal} diff --git a/man/discrete_scale.Rd b/man/discrete_scale.Rd index 87f0fb8100..3085e9d00d 100644 --- a/man/discrete_scale.Rd +++ b/man/discrete_scale.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/scale-.r \name{discrete_scale} \alias{discrete_scale} -\title{Discrete scale constructor.} +\title{Discrete scale constructor} \usage{ discrete_scale(aesthetics, scale_name, palette, name = waiver(), breaks = waiver(), labels = waiver(), limits = NULL, @@ -11,13 +11,14 @@ discrete_scale(aesthetics, scale_name, palette, name = waiver(), super = ScaleDiscrete) } \arguments{ -\item{aesthetics}{The names of the aesthetics that this scale works with} +\item{aesthetics}{The names of the aesthetics that this scale works with.} -\item{scale_name}{The name of the scale} +\item{scale_name}{The name of the scale that should be used for error messages +associated with this scale.} \item{palette}{A palette function that when called with a single integer argument (the number of levels in the scale) returns the values that -they should take.} +they should take (e.g., \code{\link[scales:hue_pal]{scales::hue_pal()}}).} \item{name}{The name of the scale. Used as the axis or legend title. If \code{waiver()}, the default, the name of the scale is taken from the first @@ -27,8 +28,7 @@ omitted.} \item{breaks}{One of: \itemize{ \item \code{NULL} for no breaks -\item \code{waiver()} for the default breaks computed by the -transformation object +\item \code{waiver()} for the default breaks (the scale limits) \item A character vector of breaks \item A function that takes the limits as input and returns breaks as output @@ -47,8 +47,8 @@ as output \item{limits}{A character vector that defines possible values of the scale and their order.} -\item{expand}{Vector of range expansion constants used to add some -padding around the data, to ensure that they are placed some distance +\item{expand}{For position scales, a vector of range expansion constants used to add some +padding around the data to ensure that they are placed some distance away from the axes. Use the convenience function \code{\link[=expand_scale]{expand_scale()}} to generate the values for the \code{expand} argument. The defaults are to expand the scale by 5\% on each side for continuous variables, and by @@ -67,14 +67,14 @@ The default, \code{TRUE}, uses the levels that appear in the data; \code{FALSE} uses all the levels in the factor.} \item{guide}{A function used to create a guide or its name. See -\code{\link[=guides]{guides()}} for more info.} +\code{\link[=guides]{guides()}} for more information.} -\item{position}{The position of the axis. "left" or "right" for vertical -scales, "top" or "bottom" for horizontal scales} +\item{position}{For position scales, The position of the axis. +\code{left} or \code{right} for y axes, \code{top} or \code{bottom} for x axes.} \item{super}{The super class to use for the constructed scale} } \description{ -Discrete scale constructor. +Discrete scale constructor } \keyword{internal} diff --git a/man/ggplot2-ggproto.Rd b/man/ggplot2-ggproto.Rd index b7afad3c3a..7c030bfb2e 100644 --- a/man/ggplot2-ggproto.Rd +++ b/man/ggplot2-ggproto.Rd @@ -401,12 +401,80 @@ that must be present for this position adjustment to work. \section{Scales}{ -All \code{scale_*} functions (like \code{scale_x_continuous}) return a -\code{Scale*} object (like \code{ScaleContinuous}). The \code{Scale*} -object represents a single scale. +All \code{scale_*} functions like \code{\link[=scale_x_continuous]{scale_x_continuous()}} return a \code{Scale*} +object like \code{ScaleContinuous}. Each of the \code{Scale*} objects is a \code{\link[=ggproto]{ggproto()}} +object, descended from the top-level \code{Scale}. -Each of the \code{Scale*} objects is a \code{\link[=ggproto]{ggproto()}} object, -descended from the top-level \code{Scale}. +Properties not documented in \code{\link[=continuous_scale]{continuous_scale()}} or \code{\link[=discrete_scale]{discrete_scale()}}: +\itemize{ +\item \code{call} The call to \code{\link[=continuous_scale]{continuous_scale()}} or \code{\link[=discrete_scale]{discrete_scale()}} that constructed +the scale. +\item \code{range} One of \code{continuous_range()} or \code{discrete_range()}. +} + +Methods: +\itemize{ +\item \code{is_discrete()} Returns \code{TRUE} if the scale is a discrete scale +\item \code{is_empty()} Returns \code{TRUE} if the scale contains no information (i.e., +it has no information with which to calculate its \code{limits}). +\item \code{clone()} Returns a copy of the scale that can be trained +independently without affecting the original scale. +\item \code{transform()} Transforms a vector of values using \code{self$trans}. +This occurs before the \code{Stat} is calculated. +\item \code{train()} Update the \code{self$range} of observed (transformed) data values with +a vector of (possibly) new values. +\item \code{reset()} Reset the \code{self$range} of observed data values. For discrete +position scales, only the continuous range is reset. +\item \code{map()} Map transformed data values to some output value as +determined by \code{self$rescale()} and \code{self$pallete} (except for position scales, +which do not use the default implementation of this method). The output corresponds +to the transformed data value in aesthetic space (e.g., a color, line width, or size). +\item \code{rescale()} Rescale transformed data to the the range 0, 1. This is most useful for +position scales. For continuous scales, \code{rescale()} uses the \code{rescaler} that +was provided to the constructor. \code{rescale()} does not apply \code{self$oob()} to +its input, which means that discrete values outside \code{limits} will be \code{NA}, and +values that are outside \code{range} will have values less than 0 or greater than 1. +This allows guides more control over how out-of-bounds values are displayed. +\item \code{transform_df()}, \code{train_df()}, \code{map_df()} These \code{_df} variants +accept a data frame, and apply the \code{transform}, \code{train}, and \code{map} methods +(respectively) to the columns whose names are in \code{self$aesthetics}. +\item \code{get_limits()} Calculates the final scale limits in transformed data space +based on the combination of \code{self$limits} and/or the range of observed values +(\code{self$range}). +\item \code{get_breaks()} Calculates the final scale breaks in transformed data space +based on on the combination of \code{self$breaks}, \code{self$trans$breaks()} (for +continuous scales), and \code{limits}. Breaks outside of \code{limits} are assigned +a value of \code{NA} (continuous scales) or dropped (discrete scales). +\item \code{get_labels()} Calculates labels for a given set of (transformed) \code{breaks} +based on the combination of \code{self$labels} and \code{breaks}. +\item \code{get_breaks_minor()} For continuous scales, calculates the final scale minor breaks +in transformed data space based on the rescaled \code{breaks}, the value of \code{self$minor_breaks}, +and the value of \code{self$trans$minor_breaks()}. Discrete scales always return \code{NULL}. +\item \code{make_title()} Hook to modify the title that is calculated during guide construction +(for non-position scales) or when the \code{Layout} calculates the x and y labels +(position scales). +} + +These methods are only valid for position (x and y) scales: +\itemize{ +\item \code{dimension()} For continuous scales, the dimension is the same concept as the limits. +For discrete scales, \code{dimension()} returns a continuous range, where the limits +would be placed at integer positions. \code{dimension()} optionally expands +this range given an expantion of length 4 (see \code{\link[=expand_scale]{expand_scale()}}). +\item \code{break_info()} Returns a \code{list()} with calculated values needed for the \code{Coord} +to transform values in transformed data space. Axis and grid guides also use +these values to draw guides. This is called with +a (usually expanded) continuous range, such as that returned by \code{self$dimension()} +(even for discrete scales). The list has components \code{major_source} +(\code{self$get_breaks()} for continuous scales, or \code{seq_along(self$get_breaks())} +for discrete scales), \code{major} (the rescaled value of \code{major_source}, ignoring +\code{self$rescaler}), \code{minor} (the rescaled value of \code{minor_source}, ignoring +\code{self$rescaler}), \code{range} (the range that was passed in to \code{break_info()}), +\code{labels} (the label values, one for each element in \code{breaks}). +\item \code{axis_order()} One of \code{c("primary", "secondary")} or \code{c("secondary", "primary")} +\item \code{make_sec_title()} Hook to modify the title for the second axis that is calculated +when the \code{Layout} calculates the x and y labels. +} } \seealso{ diff --git a/man/scale_continuous.Rd b/man/scale_continuous.Rd index 1806550a1f..7baeff1789 100644 --- a/man/scale_continuous.Rd +++ b/man/scale_continuous.Rd @@ -43,10 +43,10 @@ omitted.} \itemize{ \item \code{NULL} for no breaks \item \code{waiver()} for the default breaks computed by the -transformation object +\link[scales:trans_new]{transformation object} \item A numeric vector of positions \item A function that takes the limits as input and returns breaks -as output +as output (e.g., a function returned by \code{\link[scales:extended_breaks]{scales::extended_breaks()}}) }} \item{minor_breaks}{One of: @@ -77,32 +77,33 @@ Use \code{NA} to refer to the existing minimum or maximum new limits }} -\item{expand}{Vector of range expansion constants used to add some -padding around the data, to ensure that they are placed some distance +\item{expand}{For position scales, a vector of range expansion constants used to add some +padding around the data to ensure that they are placed some distance away from the axes. Use the convenience function \code{\link[=expand_scale]{expand_scale()}} to generate the values for the \code{expand} argument. The defaults are to expand the scale by 5\% on each side for continuous variables, and by 0.6 units on each side for discrete variables.} \item{oob}{Function that handles limits outside of the scale limits -(out of bounds). The default replaces out of bounds values with \code{NA}.} +(out of bounds). The default (\code{\link[scales:censor]{scales::censor()}}) replaces out of +bounds values with \code{NA}.} \item{na.value}{Missing values will be replaced with this value.} -\item{trans}{Either the name of a transformation object, or the -object itself. Built-in transformations include "asn", "atanh", +\item{trans}{For continuous scales, the name of a transformation object +or the object itself. Built-in transformations include "asn", "atanh", "boxcox", "date", "exp", "hms", "identity", "log", "log10", "log1p", "log2", "logit", "modulus", "probability", "probit", "pseudo_log", "reciprocal", "reverse", "sqrt" and "time". A transformation object bundles together a transform, its inverse, and methods for generating breaks and labels. Transformation objects -are defined in the scales package, and are called \code{name_trans}, e.g. -\code{\link[scales:boxcox_trans]{scales::boxcox_trans()}}. You can create your own +are defined in the scales package, and are called \code{_trans} (e.g., +\code{\link[scales:boxcox_trans]{scales::boxcox_trans()}}). You can create your own transformation with \code{\link[scales:trans_new]{scales::trans_new()}}.} -\item{position}{The position of the axis. "left" or "right" for vertical -scales, "top" or "bottom" for horizontal scales} +\item{position}{For position scales, The position of the axis. +\code{left} or \code{right} for y axes, \code{top} or \code{bottom} for x axes.} \item{sec.axis}{specify a secondary axis} diff --git a/man/scale_date.Rd b/man/scale_date.Rd index f09a0f339c..696312c1a6 100644 --- a/man/scale_date.Rd +++ b/man/scale_date.Rd @@ -97,15 +97,15 @@ Use \code{NA} to refer to the existing minimum or maximum new limits }} -\item{expand}{Vector of range expansion constants used to add some -padding around the data, to ensure that they are placed some distance +\item{expand}{For position scales, a vector of range expansion constants used to add some +padding around the data to ensure that they are placed some distance away from the axes. Use the convenience function \code{\link[=expand_scale]{expand_scale()}} to generate the values for the \code{expand} argument. The defaults are to expand the scale by 5\% on each side for continuous variables, and by 0.6 units on each side for discrete variables.} -\item{position}{The position of the axis. "left" or "right" for vertical -scales, "top" or "bottom" for horizontal scales} +\item{position}{For position scales, The position of the axis. +\code{left} or \code{right} for y axes, \code{top} or \code{bottom} for x axes.} \item{sec.axis}{specify a secondary axis} @@ -113,7 +113,8 @@ scales, "top" or "bottom" for horizontal scales} (\code{NULL}) uses the timezone encoded in the data.} \item{oob}{Function that handles limits outside of the scale limits -(out of bounds). The default replaces out of bounds values with \code{NA}.} +(out of bounds). The default (\code{\link[scales:censor]{scales::censor()}}) replaces out of +bounds values with \code{NA}.} \item{na.value}{Missing values will be replaced with this value.} } diff --git a/man/scale_discrete.Rd b/man/scale_discrete.Rd index 457785b76f..9688612709 100644 --- a/man/scale_discrete.Rd +++ b/man/scale_discrete.Rd @@ -14,12 +14,11 @@ scale_y_discrete(..., expand = waiver(), position = "left") \describe{ \item{palette}{A palette function that when called with a single integer argument (the number of levels in the scale) returns the values that -they should take.} +they should take (e.g., \code{\link[scales:hue_pal]{scales::hue_pal()}}).} \item{breaks}{One of: \itemize{ \item \code{NULL} for no breaks -\item \code{waiver()} for the default breaks computed by the -transformation object +\item \code{waiver()} for the default breaks (the scale limits) \item A character vector of breaks \item A function that takes the limits as input and returns breaks as output @@ -35,8 +34,9 @@ from a discrete scale, specify \code{na.translate = FALSE}.} \item{na.value}{If \code{na.translate = TRUE}, what value aesthetic value should missing be displayed as? Does not apply to position scales where \code{NA} is always placed at the far right.} - \item{aesthetics}{The names of the aesthetics that this scale works with} - \item{scale_name}{The name of the scale} + \item{aesthetics}{The names of the aesthetics that this scale works with.} + \item{scale_name}{The name of the scale that should be used for error messages +associated with this scale.} \item{name}{The name of the scale. Used as the axis or legend title. If \code{waiver()}, the default, the name of the scale is taken from the first mapping used for that aesthetic. If \code{NULL}, the legend title will be @@ -50,20 +50,28 @@ transformation object \item A function that takes the breaks as input and returns labels as output }} + \item{expand}{For position scales, a vector of range expansion constants used to add some +padding around the data to ensure that they are placed some distance +away from the axes. Use the convenience function \code{\link[=expand_scale]{expand_scale()}} +to generate the values for the \code{expand} argument. The defaults are to +expand the scale by 5\% on each side for continuous variables, and by +0.6 units on each side for discrete variables.} \item{guide}{A function used to create a guide or its name. See -\code{\link[=guides]{guides()}} for more info.} +\code{\link[=guides]{guides()}} for more information.} + \item{position}{For position scales, The position of the axis. +\code{left} or \code{right} for y axes, \code{top} or \code{bottom} for x axes.} \item{super}{The super class to use for the constructed scale} }} -\item{expand}{Vector of range expansion constants used to add some -padding around the data, to ensure that they are placed some distance +\item{expand}{For position scales, a vector of range expansion constants used to add some +padding around the data to ensure that they are placed some distance away from the axes. Use the convenience function \code{\link[=expand_scale]{expand_scale()}} to generate the values for the \code{expand} argument. The defaults are to expand the scale by 5\% on each side for continuous variables, and by 0.6 units on each side for discrete variables.} -\item{position}{The position of the axis. \code{left} or \code{right} for y -axes, \code{top} or \code{bottom} for x axes} +\item{position}{For position scales, The position of the axis. +\code{left} or \code{right} for y axes, \code{top} or \code{bottom} for x axes.} } \description{ You can use continuous positions even with a discrete position scale - diff --git a/man/scale_gradient.Rd b/man/scale_gradient.Rd index 44237ace91..6a741ca598 100644 --- a/man/scale_gradient.Rd +++ b/man/scale_gradient.Rd @@ -44,10 +44,11 @@ scale_fill_gradientn(..., colours, values = NULL, space = "Lab", \arguments{ \item{...}{Arguments passed on to \code{continuous_scale} \describe{ - \item{scale_name}{The name of the scale} + \item{scale_name}{The name of the scale that should be used for error messages +associated with this scale.} \item{palette}{A palette function that when called with a numeric vector with -values between 0 and 1 returns the corresponding values in the range the -scale maps to.} +values between 0 and 1 returns the corresponding output values +(e.g., \code{\link[scales:area_pal]{scales::area_pal()}}).} \item{name}{The name of the scale. Used as the axis or legend title. If \code{waiver()}, the default, the name of the scale is taken from the first mapping used for that aesthetic. If \code{NULL}, the legend title will be @@ -56,10 +57,10 @@ omitted.} \itemize{ \item \code{NULL} for no breaks \item \code{waiver()} for the default breaks computed by the -transformation object +\link[scales:trans_new]{transformation object} \item A numeric vector of positions \item A function that takes the limits as input and returns breaks -as output +as output (e.g., a function returned by \code{\link[scales:extended_breaks]{scales::extended_breaks()}}) }} \item{minor_breaks}{One of: \itemize{ @@ -86,31 +87,34 @@ Use \code{NA} to refer to the existing minimum or maximum \item A function that accepts the existing (automatic) limits and returns new limits }} - \item{rescaler}{Used by diverging and n colour gradients -(i.e. \code{\link[=scale_colour_gradient2]{scale_colour_gradient2()}}, \code{\link[=scale_colour_gradientn]{scale_colour_gradientn()}}). -A function used to scale the input values to the range [0, 1].} + \item{rescaler}{A function used to scale the input values to the +range [0, 1]. This is always \code{\link[scales:rescale]{scales::rescale()}}, except for +diverging and n colour gradients (i.e., \code{\link[=scale_colour_gradient2]{scale_colour_gradient2()}}, +\code{\link[=scale_colour_gradientn]{scale_colour_gradientn()}}). The \code{rescaler} is ignored by position +scales, which ways use \code{\link[scales:rescale]{scales::rescale()}}.} \item{oob}{Function that handles limits outside of the scale limits -(out of bounds). The default replaces out of bounds values with \code{NA}.} - \item{trans}{Either the name of a transformation object, or the -object itself. Built-in transformations include "asn", "atanh", +(out of bounds). The default (\code{\link[scales:censor]{scales::censor()}}) replaces out of +bounds values with \code{NA}.} + \item{trans}{For continuous scales, the name of a transformation object +or the object itself. Built-in transformations include "asn", "atanh", "boxcox", "date", "exp", "hms", "identity", "log", "log10", "log1p", "log2", "logit", "modulus", "probability", "probit", "pseudo_log", "reciprocal", "reverse", "sqrt" and "time". A transformation object bundles together a transform, its inverse, and methods for generating breaks and labels. Transformation objects -are defined in the scales package, and are called \code{name_trans}, e.g. -\code{\link[scales:boxcox_trans]{scales::boxcox_trans()}}. You can create your own +are defined in the scales package, and are called \code{_trans} (e.g., +\code{\link[scales:boxcox_trans]{scales::boxcox_trans()}}). You can create your own transformation with \code{\link[scales:trans_new]{scales::trans_new()}}.} - \item{position}{The position of the axis. "left" or "right" for vertical -scales, "top" or "bottom" for horizontal scales} - \item{super}{The super class to use for the constructed scale} - \item{expand}{Vector of range expansion constants used to add some -padding around the data, to ensure that they are placed some distance + \item{expand}{For position scales, a vector of range expansion constants used to add some +padding around the data to ensure that they are placed some distance away from the axes. Use the convenience function \code{\link[=expand_scale]{expand_scale()}} to generate the values for the \code{expand} argument. The defaults are to expand the scale by 5\% on each side for continuous variables, and by 0.6 units on each side for discrete variables.} + \item{position}{For position scales, The position of the axis. +\code{left} or \code{right} for y axes, \code{top} or \code{bottom} for x axes.} + \item{super}{The super class to use for the constructed scale} }} \item{low, high}{Colours for low and high ends of the gradient.} diff --git a/man/scale_grey.Rd b/man/scale_grey.Rd index cc75334ada..ee7ffd860f 100644 --- a/man/scale_grey.Rd +++ b/man/scale_grey.Rd @@ -17,12 +17,11 @@ scale_fill_grey(..., start = 0.2, end = 0.8, na.value = "red", \describe{ \item{palette}{A palette function that when called with a single integer argument (the number of levels in the scale) returns the values that -they should take.} +they should take (e.g., \code{\link[scales:hue_pal]{scales::hue_pal()}}).} \item{breaks}{One of: \itemize{ \item \code{NULL} for no breaks -\item \code{waiver()} for the default breaks computed by the -transformation object +\item \code{waiver()} for the default breaks (the scale limits) \item A character vector of breaks \item A function that takes the limits as input and returns breaks as output @@ -38,8 +37,9 @@ from a discrete scale, specify \code{na.translate = FALSE}.} \item{na.value}{If \code{na.translate = TRUE}, what value aesthetic value should missing be displayed as? Does not apply to position scales where \code{NA} is always placed at the far right.} - \item{aesthetics}{The names of the aesthetics that this scale works with} - \item{scale_name}{The name of the scale} + \item{aesthetics}{The names of the aesthetics that this scale works with.} + \item{scale_name}{The name of the scale that should be used for error messages +associated with this scale.} \item{name}{The name of the scale. Used as the axis or legend title. If \code{waiver()}, the default, the name of the scale is taken from the first mapping used for that aesthetic. If \code{NULL}, the legend title will be @@ -53,16 +53,16 @@ transformation object \item A function that takes the breaks as input and returns labels as output }} - \item{expand}{Vector of range expansion constants used to add some -padding around the data, to ensure that they are placed some distance + \item{expand}{For position scales, a vector of range expansion constants used to add some +padding around the data to ensure that they are placed some distance away from the axes. Use the convenience function \code{\link[=expand_scale]{expand_scale()}} to generate the values for the \code{expand} argument. The defaults are to expand the scale by 5\% on each side for continuous variables, and by 0.6 units on each side for discrete variables.} \item{guide}{A function used to create a guide or its name. See -\code{\link[=guides]{guides()}} for more info.} - \item{position}{The position of the axis. "left" or "right" for vertical -scales, "top" or "bottom" for horizontal scales} +\code{\link[=guides]{guides()}} for more information.} + \item{position}{For position scales, The position of the axis. +\code{left} or \code{right} for y axes, \code{top} or \code{bottom} for x axes.} \item{super}{The super class to use for the constructed scale} }} diff --git a/man/scale_hue.Rd b/man/scale_hue.Rd index f491673668..85d610e03a 100644 --- a/man/scale_hue.Rd +++ b/man/scale_hue.Rd @@ -22,12 +22,11 @@ scale_fill_hue(..., h = c(0, 360) + 15, c = 100, l = 65, \describe{ \item{palette}{A palette function that when called with a single integer argument (the number of levels in the scale) returns the values that -they should take.} +they should take (e.g., \code{\link[scales:hue_pal]{scales::hue_pal()}}).} \item{breaks}{One of: \itemize{ \item \code{NULL} for no breaks -\item \code{waiver()} for the default breaks computed by the -transformation object +\item \code{waiver()} for the default breaks (the scale limits) \item A character vector of breaks \item A function that takes the limits as input and returns breaks as output @@ -43,7 +42,8 @@ from a discrete scale, specify \code{na.translate = FALSE}.} \item{na.value}{If \code{na.translate = TRUE}, what value aesthetic value should missing be displayed as? Does not apply to position scales where \code{NA} is always placed at the far right.} - \item{scale_name}{The name of the scale} + \item{scale_name}{The name of the scale that should be used for error messages +associated with this scale.} \item{name}{The name of the scale. Used as the axis or legend title. If \code{waiver()}, the default, the name of the scale is taken from the first mapping used for that aesthetic. If \code{NULL}, the legend title will be @@ -57,16 +57,16 @@ transformation object \item A function that takes the breaks as input and returns labels as output }} - \item{expand}{Vector of range expansion constants used to add some -padding around the data, to ensure that they are placed some distance + \item{expand}{For position scales, a vector of range expansion constants used to add some +padding around the data to ensure that they are placed some distance away from the axes. Use the convenience function \code{\link[=expand_scale]{expand_scale()}} to generate the values for the \code{expand} argument. The defaults are to expand the scale by 5\% on each side for continuous variables, and by 0.6 units on each side for discrete variables.} \item{guide}{A function used to create a guide or its name. See -\code{\link[=guides]{guides()}} for more info.} - \item{position}{The position of the axis. "left" or "right" for vertical -scales, "top" or "bottom" for horizontal scales} +\code{\link[=guides]{guides()}} for more information.} + \item{position}{For position scales, The position of the axis. +\code{left} or \code{right} for y axes, \code{top} or \code{bottom} for x axes.} \item{super}{The super class to use for the constructed scale} }} diff --git a/man/scale_linetype.Rd b/man/scale_linetype.Rd index 68fc2b88f9..dd4588a11e 100644 --- a/man/scale_linetype.Rd +++ b/man/scale_linetype.Rd @@ -17,12 +17,11 @@ scale_linetype_discrete(..., na.value = "blank") \describe{ \item{palette}{A palette function that when called with a single integer argument (the number of levels in the scale) returns the values that -they should take.} +they should take (e.g., \code{\link[scales:hue_pal]{scales::hue_pal()}}).} \item{breaks}{One of: \itemize{ \item \code{NULL} for no breaks -\item \code{waiver()} for the default breaks computed by the -transformation object +\item \code{waiver()} for the default breaks (the scale limits) \item A character vector of breaks \item A function that takes the limits as input and returns breaks as output @@ -35,8 +34,9 @@ The default, \code{TRUE}, uses the levels that appear in the data; \item{na.translate}{Unlike continuous scales, discrete scales can easily show missing values, and do so by default. If you want to remove missing values from a discrete scale, specify \code{na.translate = FALSE}.} - \item{aesthetics}{The names of the aesthetics that this scale works with} - \item{scale_name}{The name of the scale} + \item{aesthetics}{The names of the aesthetics that this scale works with.} + \item{scale_name}{The name of the scale that should be used for error messages +associated with this scale.} \item{name}{The name of the scale. Used as the axis or legend title. If \code{waiver()}, the default, the name of the scale is taken from the first mapping used for that aesthetic. If \code{NULL}, the legend title will be @@ -51,7 +51,7 @@ transformation object as output }} \item{guide}{A function used to create a guide or its name. See -\code{\link[=guides]{guides()}} for more info.} +\code{\link[=guides]{guides()}} for more information.} \item{super}{The super class to use for the constructed scale} }} diff --git a/man/scale_manual.Rd b/man/scale_manual.Rd index f69428d917..20f3b194ba 100644 --- a/man/scale_manual.Rd +++ b/man/scale_manual.Rd @@ -30,12 +30,11 @@ scale_discrete_manual(aesthetics, ..., values) \describe{ \item{palette}{A palette function that when called with a single integer argument (the number of levels in the scale) returns the values that -they should take.} +they should take (e.g., \code{\link[scales:hue_pal]{scales::hue_pal()}}).} \item{breaks}{One of: \itemize{ \item \code{NULL} for no breaks -\item \code{waiver()} for the default breaks computed by the -transformation object +\item \code{waiver()} for the default breaks (the scale limits) \item A character vector of breaks \item A function that takes the limits as input and returns breaks as output @@ -51,7 +50,8 @@ from a discrete scale, specify \code{na.translate = FALSE}.} \item{na.value}{If \code{na.translate = TRUE}, what value aesthetic value should missing be displayed as? Does not apply to position scales where \code{NA} is always placed at the far right.} - \item{scale_name}{The name of the scale} + \item{scale_name}{The name of the scale that should be used for error messages +associated with this scale.} \item{name}{The name of the scale. Used as the axis or legend title. If \code{waiver()}, the default, the name of the scale is taken from the first mapping used for that aesthetic. If \code{NULL}, the legend title will be @@ -66,7 +66,7 @@ transformation object as output }} \item{guide}{A function used to create a guide or its name. See -\code{\link[=guides]{guides()}} for more info.} +\code{\link[=guides]{guides()}} for more information.} \item{super}{The super class to use for the constructed scale} }} diff --git a/man/scale_shape.Rd b/man/scale_shape.Rd index 58bb2e265e..2763e5e984 100644 --- a/man/scale_shape.Rd +++ b/man/scale_shape.Rd @@ -14,12 +14,11 @@ scale_shape(..., solid = TRUE) \describe{ \item{palette}{A palette function that when called with a single integer argument (the number of levels in the scale) returns the values that -they should take.} +they should take (e.g., \code{\link[scales:hue_pal]{scales::hue_pal()}}).} \item{breaks}{One of: \itemize{ \item \code{NULL} for no breaks -\item \code{waiver()} for the default breaks computed by the -transformation object +\item \code{waiver()} for the default breaks (the scale limits) \item A character vector of breaks \item A function that takes the limits as input and returns breaks as output @@ -35,8 +34,9 @@ from a discrete scale, specify \code{na.translate = FALSE}.} \item{na.value}{If \code{na.translate = TRUE}, what value aesthetic value should missing be displayed as? Does not apply to position scales where \code{NA} is always placed at the far right.} - \item{aesthetics}{The names of the aesthetics that this scale works with} - \item{scale_name}{The name of the scale} + \item{aesthetics}{The names of the aesthetics that this scale works with.} + \item{scale_name}{The name of the scale that should be used for error messages +associated with this scale.} \item{name}{The name of the scale. Used as the axis or legend title. If \code{waiver()}, the default, the name of the scale is taken from the first mapping used for that aesthetic. If \code{NULL}, the legend title will be @@ -51,7 +51,7 @@ transformation object as output }} \item{guide}{A function used to create a guide or its name. See -\code{\link[=guides]{guides()}} for more info.} +\code{\link[=guides]{guides()}} for more information.} \item{super}{The super class to use for the constructed scale} }} diff --git a/man/scale_size.Rd b/man/scale_size.Rd index 75820050ce..dd5a9918d3 100644 --- a/man/scale_size.Rd +++ b/man/scale_size.Rd @@ -31,10 +31,10 @@ omitted.} \itemize{ \item \code{NULL} for no breaks \item \code{waiver()} for the default breaks computed by the -transformation object +\link[scales:trans_new]{transformation object} \item A numeric vector of positions \item A function that takes the limits as input and returns breaks -as output +as output (e.g., a function returned by \code{\link[scales:extended_breaks]{scales::extended_breaks()}}) }} \item{labels}{One of: @@ -59,20 +59,20 @@ new limits \item{range}{a numeric vector of length 2 that specifies the minimum and maximum size of the plotting symbol after transformation.} -\item{trans}{Either the name of a transformation object, or the -object itself. Built-in transformations include "asn", "atanh", +\item{trans}{For continuous scales, the name of a transformation object +or the object itself. Built-in transformations include "asn", "atanh", "boxcox", "date", "exp", "hms", "identity", "log", "log10", "log1p", "log2", "logit", "modulus", "probability", "probit", "pseudo_log", "reciprocal", "reverse", "sqrt" and "time". A transformation object bundles together a transform, its inverse, and methods for generating breaks and labels. Transformation objects -are defined in the scales package, and are called \code{name_trans}, e.g. -\code{\link[scales:boxcox_trans]{scales::boxcox_trans()}}. You can create your own +are defined in the scales package, and are called \code{_trans} (e.g., +\code{\link[scales:boxcox_trans]{scales::boxcox_trans()}}). You can create your own transformation with \code{\link[scales:trans_new]{scales::trans_new()}}.} \item{guide}{A function used to create a guide or its name. See -\code{\link[=guides]{guides()}} for more info.} +\code{\link[=guides]{guides()}} for more information.} \item{...}{Arguments passed on to \code{continuous_scale} \describe{ @@ -84,10 +84,10 @@ omitted.} \itemize{ \item \code{NULL} for no breaks \item \code{waiver()} for the default breaks computed by the -transformation object +\link[scales:trans_new]{transformation object} \item A numeric vector of positions \item A function that takes the limits as input and returns breaks -as output +as output (e.g., a function returned by \code{\link[scales:extended_breaks]{scales::extended_breaks()}}) }} \item{minor_breaks}{One of: \itemize{ @@ -115,30 +115,31 @@ Use \code{NA} to refer to the existing minimum or maximum new limits }} \item{oob}{Function that handles limits outside of the scale limits -(out of bounds). The default replaces out of bounds values with \code{NA}.} +(out of bounds). The default (\code{\link[scales:censor]{scales::censor()}}) replaces out of +bounds values with \code{NA}.} \item{na.value}{Missing values will be replaced with this value.} - \item{trans}{Either the name of a transformation object, or the -object itself. Built-in transformations include "asn", "atanh", + \item{trans}{For continuous scales, the name of a transformation object +or the object itself. Built-in transformations include "asn", "atanh", "boxcox", "date", "exp", "hms", "identity", "log", "log10", "log1p", "log2", "logit", "modulus", "probability", "probit", "pseudo_log", "reciprocal", "reverse", "sqrt" and "time". A transformation object bundles together a transform, its inverse, and methods for generating breaks and labels. Transformation objects -are defined in the scales package, and are called \code{name_trans}, e.g. -\code{\link[scales:boxcox_trans]{scales::boxcox_trans()}}. You can create your own +are defined in the scales package, and are called \code{_trans} (e.g., +\code{\link[scales:boxcox_trans]{scales::boxcox_trans()}}). You can create your own transformation with \code{\link[scales:trans_new]{scales::trans_new()}}.} \item{guide}{A function used to create a guide or its name. See -\code{\link[=guides]{guides()}} for more info.} - \item{position}{The position of the axis. "left" or "right" for vertical -scales, "top" or "bottom" for horizontal scales} - \item{super}{The super class to use for the constructed scale} - \item{expand}{Vector of range expansion constants used to add some -padding around the data, to ensure that they are placed some distance +\code{\link[=guides]{guides()}} for more information.} + \item{expand}{For position scales, a vector of range expansion constants used to add some +padding around the data to ensure that they are placed some distance away from the axes. Use the convenience function \code{\link[=expand_scale]{expand_scale()}} to generate the values for the \code{expand} argument. The defaults are to expand the scale by 5\% on each side for continuous variables, and by 0.6 units on each side for discrete variables.} + \item{position}{For position scales, The position of the axis. +\code{left} or \code{right} for y axes, \code{top} or \code{bottom} for x axes.} + \item{super}{The super class to use for the constructed scale} }} \item{max_size}{Size of largest points.} diff --git a/man/scale_viridis.Rd b/man/scale_viridis.Rd index 621aa8c6f3..a3817e2e30 100644 --- a/man/scale_viridis.Rd +++ b/man/scale_viridis.Rd @@ -59,7 +59,7 @@ other values are deprecated.} \item{na.value}{Missing values will be replaced with this value.} \item{guide}{A function used to create a guide or its name. See -\code{\link[=guides]{guides()}} for more info.} +\code{\link[=guides]{guides()}} for more information.} } \description{ The \code{viridis} scales provide colour maps that are perceptually uniform in both diff --git a/tests/testthat/test-data.r b/tests/testthat/test-data.r index 83733e60e1..abe4d88943 100644 --- a/tests/testthat/test-data.r +++ b/tests/testthat/test-data.r @@ -8,7 +8,7 @@ test_that("stringsAsFactors doesn't affect results", { dat.factor <- data_frame(x = letters[5:1], y = 1:5, stringsAsFactors = TRUE) base <- ggplot(mapping = aes(x, y)) + geom_point() - xlabels <- function(x) x$layout$panel_params[[1]]$x.labels + xlabels <- function(x) x$layout$panel_params[[1]]$x$get_labels() options(stringsAsFactors = TRUE) char_true <- ggplot_build(base %+% dat.character) diff --git a/tests/testthat/test-stat-bin.R b/tests/testthat/test-stat-bin.R index 5e70617b8b..c76520a4c6 100644 --- a/tests/testthat/test-stat-bin.R +++ b/tests/testthat/test-stat-bin.R @@ -168,6 +168,6 @@ test_that("stat_count preserves x order for continuous and discrete", { mtcars$carb3 <- factor(mtcars$carb, levels = c(4,1,2,3,6,8)) b <- ggplot_build(ggplot(mtcars, aes(carb3)) + geom_bar()) expect_identical(b$data[[1]]$x, 1:6) - expect_identical(b$layout$panel_params[[1]]$x.labels, c("4","1","2","3","6","8")) + expect_identical(b$layout$panel_params[[1]]$x$get_labels(), c("4","1","2","3","6","8")) expect_identical(b$data[[1]]$y, c(10,7,10,3,1,1)) })