diff --git a/DESCRIPTION b/DESCRIPTION index 99cf607d29..e244a932ad 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -254,6 +254,6 @@ Collate: 'zxx.r' 'zzz.r' VignetteBuilder: knitr -RoxygenNote: 7.0.2 +RoxygenNote: 7.1.0 Roxygen: list(markdown = TRUE) Encoding: UTF-8 diff --git a/NAMESPACE b/NAMESPACE index efeddbb12d..8f74d21e39 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -107,6 +107,7 @@ S3method(makeContext,dotstackGrob) S3method(merge_element,default) S3method(merge_element,element) S3method(merge_element,element_blank) +S3method(merge_element,list) S3method(plot,ggplot) S3method(predictdf,default) S3method(predictdf,glm) diff --git a/R/layer.r b/R/layer.r index 69abc5ec06..46741a1196 100644 --- a/R/layer.r +++ b/R/layer.r @@ -223,8 +223,7 @@ Layer <- ggproto("Layer", NULL, if (!is.null(self$geom_params$group)) { aesthetics[["group"]] <- self$aes_params$group } - - scales_add_defaults(plot$scales, data, aesthetics, plot$plot_env) + scales_add_defaults(plot$scales, data, aesthetics, plot$plot_env, plot$theme) # Evaluate aesthetics env <- child_env(baseenv(), stage = stage) @@ -320,7 +319,7 @@ Layer <- ggproto("Layer", NULL, stat_data <- new_data_frame(compact(stat_data)) # Add any new scales, if needed - scales_add_defaults(plot$scales, data, new, plot$plot_env) + scales_add_defaults(plot$scales, data, new, plot$plot_env, plot$theme) # Transform the values, if the scale say it's ok # (see stat_spoke for one exception) if (self$stat$retransform) { diff --git a/R/plot-build.r b/R/plot-build.r index dcac060141..bf07c9945a 100644 --- a/R/plot-build.r +++ b/R/plot-build.r @@ -43,6 +43,8 @@ ggplot_build.ggplot <- function(plot) { } out } + ## Build full theme combining supplied elements and current defaults + plot$theme <- plot_theme(plot) # Allow all layers to make any final adjustments based # on raw input data and plot info @@ -163,7 +165,7 @@ ggplot_gtable.ggplot_built <- function(data) { plot <- data$plot layout <- data$layout data <- data$data - theme <- plot_theme(plot) + theme <- plot$theme geom_grobs <- Map(function(l, d) l$draw_geom(d, layout), plot$layers, data) layout$setup_panel_guides(plot$guides, plot$layers, plot$mapping) diff --git a/R/scale-type.R b/R/scale-type.R index 34ccf69308..99dce37aab 100644 --- a/R/scale-type.R +++ b/R/scale-type.R @@ -1,4 +1,4 @@ -find_scale <- function(aes, x, env = parent.frame()) { +find_scale <- function(aes, x, env = parent.frame(), theme = NULL) { # Inf is ambiguous; it can be used either with continuous scales or with # discrete scales, so just skip in the hope that we will have a better guess # with the other layers @@ -8,11 +8,17 @@ find_scale <- function(aes, x, env = parent.frame()) { type <- scale_type(x) candidates <- paste("scale", aes, type, sep = "_") - for (scale in candidates) { + ## First try lookup in theme (if supplied) + default_scales <- calc_element("default.scales", theme) + scale <- default_scales[[name]] + if (!is.null(scale) && isTRUE(mode(scale) == mode)) { + return(scale) + } scale_f <- find_global(scale, env, mode = "function") - if (!is.null(scale_f)) + if (!is.null(scale_f)) { return(scale_f()) + } } # Failure to find a scale is not an error because some "aesthetics" don't diff --git a/R/scales-.r b/R/scales-.r index d56036e8cf..7e46b37b17 100644 --- a/R/scales-.r +++ b/R/scales-.r @@ -88,7 +88,7 @@ scales_transform_df <- function(scales, df) { # @param aesthetics A list of aesthetic-variable mappings. The name of each # item is the aesthetic, and the value of each item is the variable in data. -scales_add_defaults <- function(scales, data, aesthetics, env) { +scales_add_defaults <- function(scales, data, aesthetics, env, theme) { if (is.null(aesthetics)) return() names(aesthetics) <- unlist(lapply(names(aesthetics), aes_to_scale)) @@ -100,7 +100,7 @@ scales_add_defaults <- function(scales, data, aesthetics, env) { datacols <- compact(datacols) for (aes in names(datacols)) { - scales$add(find_scale(aes, datacols[[aes]], env)) + scales$add(find_scale(aes, datacols[[aes]], env, theme)) } } diff --git a/R/theme-elements.r b/R/theme-elements.r index 68bc7661d9..6566d57a6d 100644 --- a/R/theme-elements.r +++ b/R/theme-elements.r @@ -480,6 +480,7 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) { strip.placement.y = el_def("character", "strip.placement"), strip.switch.pad.grid = el_def("unit"), strip.switch.pad.wrap = el_def("unit"), + default.scales = el_def("list"), plot.background = el_def("element_rect", "rect"), plot.title = el_def("element_text", "title"), diff --git a/R/theme.r b/R/theme.r index 7cf5556b89..afd5029d76 100644 --- a/R/theme.r +++ b/R/theme.r @@ -356,6 +356,7 @@ theme <- function(line, strip.text.y, strip.switch.pad.grid, strip.switch.pad.wrap, + default.scales, ..., complete = FALSE, validate = TRUE @@ -643,6 +644,14 @@ merge_element.element <- function(new, old) { new } +#' @rdname merge_element +#' @export +merge_element.list <- function(new, old) { + overlap <- intersect(names(new), names(old)) + old <- old[setdiff(names(old), overlap)] + append(old, new) +} + #' Combine the properties of two elements #' #' @param e1 An element object diff --git a/man/diamonds.Rd b/man/diamonds.Rd index ed13e7e846..7c3be09436 100644 --- a/man/diamonds.Rd +++ b/man/diamonds.Rd @@ -4,7 +4,8 @@ \name{diamonds} \alias{diamonds} \title{Prices of over 50,000 round cut diamonds} -\format{A data frame with 53940 rows and 10 variables: +\format{ +A data frame with 53940 rows and 10 variables: \describe{ \item{price}{price in US dollars (\$326--\$18,823)} \item{carat}{weight of the diamond (0.2--5.01)} @@ -17,7 +18,8 @@ SI1, VS2, VS1, VVS2, VVS1, IF (best))} \item{z}{depth in mm (0--31.8)} \item{depth}{total depth percentage = z / mean(x, y) = 2 * z / (x + y) (43--79)} \item{table}{width of top of diamond relative to widest point (43--95)} -}} +} +} \usage{ diamonds } diff --git a/man/economics.Rd b/man/economics.Rd index e099d23e8e..d2fb819ba5 100644 --- a/man/economics.Rd +++ b/man/economics.Rd @@ -5,7 +5,8 @@ \alias{economics} \alias{economics_long} \title{US economic time series} -\format{A data frame with 574 rows and 6 variables: +\format{ +A data frame with 574 rows and 6 variables: \describe{ \item{date}{Month of data collection} \item{pce}{personal consumption expenditures, in billions of dollars, @@ -18,7 +19,10 @@ \url{http://research.stlouisfed.org/fred2/series/UEMPMED}} \item{unemploy}{number of unemployed in thousands, \url{http://research.stlouisfed.org/fred2/series/UNEMPLOY}} -}} +} + +An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 2870 rows and 4 columns. +} \usage{ economics diff --git a/man/faithfuld.Rd b/man/faithfuld.Rd index a5d8d0b7d0..5f8e0c32e9 100644 --- a/man/faithfuld.Rd +++ b/man/faithfuld.Rd @@ -4,12 +4,14 @@ \name{faithfuld} \alias{faithfuld} \title{2d density estimate of Old Faithful data} -\format{A data frame with 5,625 observations and 3 variables: +\format{ +A data frame with 5,625 observations and 3 variables: \describe{ \item{eruptions}{Eruption time in mins} \item{waiting}{Waiting time to next eruption in mins} \item{density}{2d density estimate} -}} +} +} \usage{ faithfuld } diff --git a/man/ggplot2-package.Rd b/man/ggplot2-package.Rd index 0eee1459e6..2f427a1f53 100644 --- a/man/ggplot2-package.Rd +++ b/man/ggplot2-package.Rd @@ -39,7 +39,7 @@ Authors: Other contributors: \itemize{ - \item RStudio [copyright holder] + \item RStudio [copyright holder, funder] } } diff --git a/man/graphical-units.Rd b/man/graphical-units.Rd index 1822d48011..ffd13a79a3 100644 --- a/man/graphical-units.Rd +++ b/man/graphical-units.Rd @@ -5,7 +5,11 @@ \alias{.pt} \alias{.stroke} \title{Graphical units} -\format{An object of class \code{numeric} of length 1.} +\format{ +An object of class \code{numeric} of length 1. + +An object of class \code{numeric} of length 1. +} \usage{ .pt diff --git a/man/luv_colours.Rd b/man/luv_colours.Rd index fedeb3dcef..5985911f99 100644 --- a/man/luv_colours.Rd +++ b/man/luv_colours.Rd @@ -4,11 +4,13 @@ \name{luv_colours} \alias{luv_colours} \title{\code{colors()} in Luv space} -\format{A data frame with 657 observations and 4 variables: +\format{ +A data frame with 657 observations and 4 variables: \describe{ \item{L,u,v}{Position in Luv colour space} \item{col}{Colour name} -}} +} +} \usage{ luv_colours } diff --git a/man/merge_element.Rd b/man/merge_element.Rd index 913e75ce73..760a3467af 100644 --- a/man/merge_element.Rd +++ b/man/merge_element.Rd @@ -5,6 +5,7 @@ \alias{merge_element.default} \alias{merge_element.element_blank} \alias{merge_element.element} +\alias{merge_element.list} \title{Merge a parent element into a child element} \usage{ merge_element(new, old) @@ -14,6 +15,8 @@ merge_element(new, old) \method{merge_element}{element_blank}(new, old) \method{merge_element}{element}(new, old) + +\method{merge_element}{list}(new, old) } \arguments{ \item{new}{The child element in the theme hierarchy} diff --git a/man/midwest.Rd b/man/midwest.Rd index ee8b5e85ae..4998fa6192 100644 --- a/man/midwest.Rd +++ b/man/midwest.Rd @@ -4,7 +4,8 @@ \name{midwest} \alias{midwest} \title{Midwest demographics} -\format{A data frame with 437 rows and 28 variables: +\format{ +A data frame with 437 rows and 28 variables: \describe{ \item{PID}{} \item{county}{} @@ -34,7 +35,8 @@ \item{percelderlypoverty}{} \item{inmetro}{In a metro area.} \item{category}{} -}} +} +} \usage{ midwest } diff --git a/man/mpg.Rd b/man/mpg.Rd index ec696861bd..a855a6c632 100644 --- a/man/mpg.Rd +++ b/man/mpg.Rd @@ -4,7 +4,8 @@ \name{mpg} \alias{mpg} \title{Fuel economy data from 1999 to 2008 for 38 popular models of cars} -\format{A data frame with 234 rows and 11 variables: +\format{ +A data frame with 234 rows and 11 variables: \describe{ \item{manufacturer}{manufacturer name} \item{model}{model name} @@ -17,7 +18,8 @@ \item{hwy}{highway miles per gallon} \item{fl}{fuel type} \item{class}{"type" of car} -}} +} +} \usage{ mpg } diff --git a/man/msleep.Rd b/man/msleep.Rd index a53c1cd3e2..5e513a0b87 100644 --- a/man/msleep.Rd +++ b/man/msleep.Rd @@ -4,7 +4,8 @@ \name{msleep} \alias{msleep} \title{An updated and expanded version of the mammals sleep dataset} -\format{A data frame with 83 rows and 11 variables: +\format{ +A data frame with 83 rows and 11 variables: \describe{ \item{name}{common name} \item{genus}{} @@ -17,7 +18,8 @@ \item{awake}{amount of time spent awake, in hours} \item{brainwt}{brain weight in kilograms} \item{bodywt}{body weight in kilograms} -}} +} +} \usage{ msleep } diff --git a/man/presidential.Rd b/man/presidential.Rd index 4c827f93aa..71b7b16ffe 100644 --- a/man/presidential.Rd +++ b/man/presidential.Rd @@ -4,13 +4,15 @@ \name{presidential} \alias{presidential} \title{Terms of 11 presidents from Eisenhower to Obama} -\format{A data frame with 11 rows and 4 variables: +\format{ +A data frame with 11 rows and 4 variables: \describe{ \item{name}{Last name of president} \item{start}{Presidency start date} \item{end}{Presidency end date} \item{party}{Party of president} -}} +} +} \usage{ presidential } diff --git a/man/scale_discrete.Rd b/man/scale_discrete.Rd index e5e323adae..c4bf774d42 100644 --- a/man/scale_discrete.Rd +++ b/man/scale_discrete.Rd @@ -32,8 +32,8 @@ The default, \code{TRUE}, uses the levels that appear in the data; \item{\code{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{\code{na.value}}{If \code{na.translate = TRUE}, what value aesthetic -value should missing be displayed as? Does not apply to position scales + \item{\code{na.value}}{If \code{na.translate = TRUE}, what aesthetic value should the +missing values be displayed as? Does not apply to position scales where \code{NA} is always placed at the far right.} \item{\code{aesthetics}}{The names of the aesthetics that this scale works with.} \item{\code{scale_name}}{The name of the scale that should be used for error messages diff --git a/man/scale_manual.Rd b/man/scale_manual.Rd index dd4b943056..6fbefc58f7 100644 --- a/man/scale_manual.Rd +++ b/man/scale_manual.Rd @@ -40,8 +40,8 @@ The default, \code{TRUE}, uses the levels that appear in the data; \item{\code{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{\code{na.value}}{If \code{na.translate = TRUE}, what value aesthetic -value should missing be displayed as? Does not apply to position scales + \item{\code{na.value}}{If \code{na.translate = TRUE}, what aesthetic value should the +missing values be displayed as? Does not apply to position scales where \code{NA} is always placed at the far right.} \item{\code{scale_name}}{The name of the scale that should be used for error messages associated with this scale.} diff --git a/man/scale_shape.Rd b/man/scale_shape.Rd index 0c3ba1524c..aa557fa7d6 100644 --- a/man/scale_shape.Rd +++ b/man/scale_shape.Rd @@ -35,8 +35,8 @@ The default, \code{TRUE}, uses the levels that appear in the data; \item{\code{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{\code{na.value}}{If \code{na.translate = TRUE}, what value aesthetic -value should missing be displayed as? Does not apply to position scales + \item{\code{na.value}}{If \code{na.translate = TRUE}, what aesthetic value should the +missing values be displayed as? Does not apply to position scales where \code{NA} is always placed at the far right.} \item{\code{aesthetics}}{The names of the aesthetics that this scale works with.} \item{\code{scale_name}}{The name of the scale that should be used for error messages diff --git a/man/seals.Rd b/man/seals.Rd index a3a3cccdcb..4b364a6bf2 100644 --- a/man/seals.Rd +++ b/man/seals.Rd @@ -4,7 +4,9 @@ \name{seals} \alias{seals} \title{Vector field of seal movements} -\format{A data frame with 1155 rows and 4 variables} +\format{ +A data frame with 1155 rows and 4 variables +} \usage{ seals } diff --git a/man/theme.Rd b/man/theme.Rd index 457cdb5f02..414103f42f 100644 --- a/man/theme.Rd +++ b/man/theme.Rd @@ -97,6 +97,7 @@ theme( strip.text.y, strip.switch.pad.grid, strip.switch.pad.wrap, + default.scales, ..., complete = FALSE, validate = TRUE diff --git a/man/txhousing.Rd b/man/txhousing.Rd index e9183ea37c..d983392ff8 100644 --- a/man/txhousing.Rd +++ b/man/txhousing.Rd @@ -4,7 +4,8 @@ \name{txhousing} \alias{txhousing} \title{Housing sales in TX} -\format{A data frame with 8602 observations and 9 variables: +\format{ +A data frame with 8602 observations and 9 variables: \describe{ \item{city}{Name of multiple listing service (MLS) area} \item{year,month,date}{Date} @@ -14,7 +15,8 @@ \item{listings}{Total active listings} \item{inventory}{"Months inventory": amount of time it would take to sell all current listings at current pace of sales.} -}} +} +} \usage{ txhousing }