Skip to content

Commit

Permalink
resolve merge conflict
Browse files Browse the repository at this point in the history
Merge branch 'main' into scale_palettes

# Conflicts:
#	tests/testthat/test-guides.R
  • Loading branch information
teunbrand committed Oct 31, 2024
2 parents c0b5734 + b29b831 commit d731ace
Show file tree
Hide file tree
Showing 194 changed files with 2,783 additions and 1,658 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/R-CMD-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jobs:
cache-version: 3
extra-packages: >
any::rcmdcheck,
Hmisc=?ignore-before-r=4.1.0,
Hmisc=?ignore-before-r=4.2.0,
quantreg=?ignore-before-r=4.3.0
needs: check

Expand Down
5 changes: 3 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: ggplot2
Version: 3.5.1.9000
Title: Create Elegant Data Visualisations Using the Grammar of Graphics
Version: 3.5.1.9000
Authors@R: c(
person("Hadley", "Wickham", , "hadley@posit.co", role = "aut",
comment = c(ORCID = "0000-0003-4757-117X")),
Expand Down Expand Up @@ -30,7 +30,7 @@ License: MIT + file LICENSE
URL: https://ggplot2.tidyverse.org, https://github.com/tidyverse/ggplot2
BugReports: https://github.com/tidyverse/ggplot2/issues
Depends:
R (>= 3.5)
R (>= 4.0)
Imports:
cli,
grDevices,
Expand Down Expand Up @@ -75,6 +75,7 @@ VignetteBuilder:
knitr
Config/Needs/website: ggtext, tidyr, forcats, tidyverse/tidytemplate
Config/testthat/edition: 3
Config/usethis/last-upkeep: 2024-10-24
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE)
Expand Down
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MIT License

Copyright (c) 2020 ggplot2 authors
Copyright (c) 2024 ggplot2 core developer team

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,6 @@ export(guides)
export(has_flipped_aes)
export(is.Coord)
export(is.coord)
export(is.element)
export(is.facet)
export(is.geom)
export(is.ggplot)
Expand All @@ -475,6 +474,7 @@ export(is.position)
export(is.scale)
export(is.stat)
export(is.theme)
export(is.theme_element)
export(label_both)
export(label_bquote)
export(label_context)
Expand Down
8 changes: 8 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# ggplot2 (development version)

* (internal) Using `after_scale()` in the `Geom*$default_aes()` field is now
evaluated in the context of data (@teunbrand, #6135)
* Fixed bug where binned scales wouldn't simultaneously accept transformations
and function-limits (@teunbrand, #6144).
* Fixed bug where the `ggplot2::`-prefix did not work with `stage()`
(@teunbrand, #6104).
* New `get_labs()` function for retrieving completed plot labels
(@teunbrand, #6008).
* Built-in `theme_*()` functions now have `ink` and `paper` arguments to control
Expand Down Expand Up @@ -182,6 +188,7 @@
* The ellipsis argument is now checked in `fortify()`, `get_alt_text()`,
`labs()` and several guides (@teunbrand, #3196).
* `stat_summary_bin()` no longer ignores `width` parameter (@teunbrand, #4647).
* Added `keep.zeroes` argument to `stat_bin()` (@teunbrand, #3449)

# ggplot2 3.5.1

Expand Down Expand Up @@ -228,6 +235,7 @@ documentation updates.
* `annotate()` now warns about `stat` or `position` arguments (@teunbrand, #5151)
* `guide_coloursteps(even.steps = FALSE)` now works with discrete data that has
been formatted by `cut()` (@teunbrand, #3877).
* `ggsave()` now offers to install svglite if needed (@eliocamp, #6166).

# ggplot2 3.5.0

Expand Down
55 changes: 49 additions & 6 deletions R/aes-evaluation.R
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
#' Below follows an overview of the three stages of evaluation and how aesthetic
#' evaluation can be controlled.
#'
#' ## Stage 1: direct input
#' ## Stage 1: direct input at the start
#' The default is to map at the beginning, using the layer data provided by
#' the user. If you want to map directly from the layer data you should not do
#' anything special. This is the only stage where the original layer data can
Expand Down Expand Up @@ -87,17 +87,19 @@
#' ```
#'
#' ## Complex staging
#' If you want to map the same aesthetic multiple times, e.g. map `x` to a
#' data column for the stat, but remap it for the geom, you can use the
#' `stage()` function to collect multiple mappings.
#' Sometimes, you may want to map the same aesthetic multiple times, e.g. map
#' `x` to a data column at the start for the layer stat, but remap it later to
#' a variable from the stat transformation for the layer geom. The `stage()`
#' function allows you to control multiple mappings for the same aesthetic
#' across all three stages of evaluation.
#'
#' ```r
#' # Use stage to modify the scaled fill
#' ggplot(mpg, aes(class, hwy)) +
#' geom_boxplot(aes(fill = stage(class, after_scale = alpha(fill, 0.4))))
#'
#' # Using data for computing summary, but placing label elsewhere.
#' # Also, we're making our own computed variable to use for the label.
#' # Also, we're making our own computed variables to use for the label.
#' ggplot(mpg, aes(class, displ)) +
#' geom_violin() +
#' stat_summary(
Expand All @@ -110,6 +112,11 @@
#' )
#' ```
#'
#' Conceptually, `aes(x)` is equivalent to `aes(stage(start = x))`, and
#' `aes(after_stat(count))` is equivalent to `aes(stage(after_stat = count))`,
#' and so on. `stage()` is most useful when at least two of its arguments are
#' specified.
#'
#' ## Theme access
#' The `from_theme()` function can be used to acces the [`element_geom()`]
#' fields of the `theme(geom)` argument. Using `aes(colour = from_theme(ink))`
Expand Down Expand Up @@ -332,7 +339,7 @@ strip_stage <- function(expr) {
} else if (is_call(uq_expr, "stage")) {
uq_expr <- call_match(uq_expr, stage)
# Prefer stat mapping if present, otherwise original mapping (fallback to
# scale mapping) but there should always be two arguments to stage()
# scale mapping)
uq_expr$after_stat %||% uq_expr$start %||% uq_expr$after_scale
} else {
expr
Expand All @@ -358,3 +365,39 @@ make_labels <- function(mapping) {
}
Map(default_label, names(mapping), mapping)
}

eval_aesthetics <- function(aesthetics, data, mask = NULL) {

env <- child_env(base_env())

# Here we mask functions, often to replace `stage()` with context appropriate
# functions `stage_calculated()`/`stage_scaled()`.
if (length(mask) > 0) {
aesthetics <- substitute_aes(aesthetics, mask_function, mask = mask)
}

evaled <- lapply(aesthetics, eval_tidy, data = data, env = env)
names(evaled) <- names(aesthetics)
compact(rename_aes(evaled))
}

# `mask` is a list of functions where `names(mask)` indicate names of functions
# that need to be replaced, and `mask[[i]]` is the function to replace it
# with.
mask_function <- function(x, mask) {
if (!is.call(x)) {
return(x)
}
nms <- names(mask)
x[-1] <- lapply(x[-1], mask_function, mask = mask)
if (!is_call(x, nms)) {
return(x)
}
for (nm in nms) {
if (is_call(x, nm)) {
x[[1]] <- mask[[nm]]
return(x)
}
}
}

7 changes: 5 additions & 2 deletions R/aes.R
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,12 @@ rename_aes <- function(x) {
}
x
}
substitute_aes <- function(x) {

# `x` is assumed to be a strict list of quosures;
# it should have no non-quosure constants in it, even though `aes()` allows it.
substitute_aes <- function(x, fun = standardise_aes_symbols, ...) {
x <- lapply(x, function(aesthetic) {
as_quosure(standardise_aes_symbols(quo_get_expr(aesthetic)), env = environment(aesthetic))
as_quosure(fun(quo_get_expr(aesthetic), ...), env = environment(aesthetic))
})
class(x) <- "uneval"
x
Expand Down
2 changes: 1 addition & 1 deletion R/backports.R
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,6 @@ on_load({
as.mask <- grid::as.mask
}
if ("linearGradient" %in% getNamespaceExports("grid")) {
linearGradient <- grid::linearGradient()
linearGradient <- grid::linearGradient
}
})
8 changes: 2 additions & 6 deletions R/bin.R
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,7 @@ bin_breaks <- function(breaks, closed = c("right", "left")) {

bin_breaks_width <- function(x_range, width = NULL, center = NULL,
boundary = NULL, closed = c("right", "left")) {
if (length(x_range) != 2) {
cli::cli_abort("{.arg x_range} must have two elements.")
}
check_length(x_range, 2L)

# binwidth seems to be the argument name supplied to width. (stat-bin and stat-bindot)
check_number_decimal(width, min = 0, allow_infinite = FALSE, arg = "binwidth")
Expand Down Expand Up @@ -106,9 +104,7 @@ bin_breaks_width <- function(x_range, width = NULL, center = NULL,

bin_breaks_bins <- function(x_range, bins = 30, center = NULL,
boundary = NULL, closed = c("right", "left")) {
if (length(x_range) != 2) {
cli::cli_abort("{.arg x_range} must have two elements.")
}
check_length(x_range, 2L)

check_number_whole(bins, min = 1)
if (zero_range(x_range)) {
Expand Down
12 changes: 2 additions & 10 deletions R/coord-.R
Original file line number Diff line number Diff line change
Expand Up @@ -281,14 +281,6 @@ check_coord_limits <- function(
if (is.null(limits)) {
return(invisible(NULL))
}
if (!obj_is_vector(limits) || length(limits) != 2) {
what <- "{.obj_type_friendly {limits}}"
if (is.vector(limits)) {
what <- paste0(what, " of length {length(limits)}")
}
cli::cli_abort(
paste0("{.arg {arg}} must be a vector of length 2, not ", what, "."),
call = call
)
}
check_object(limits, is_vector, "a vector", arg = arg, call = call)
check_length(limits, 2L, arg = arg, call = call)
}
4 changes: 2 additions & 2 deletions R/facet-.R
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,8 @@ Facet <- ggproto("Facet", NULL,
# Set panel names
table$layout$name <- paste(
"panel",
rep(seq_len(dim[2]), dim[1]),
rep(seq_len(dim[1]), each = dim[2]),
rep(seq_len(dim[2]), each = dim[1]),
rep(seq_len(dim[1]), dim[2]),
sep = "-"
)

Expand Down
12 changes: 2 additions & 10 deletions R/facet-wrap.R
Original file line number Diff line number Diff line change
Expand Up @@ -447,16 +447,8 @@ FacetWrap <- ggproto("FacetWrap", Facet,

draw_panels = function(self, panels, layout, x_scales, y_scales, ranges, coord, data, theme, params) {
if (inherits(coord, "CoordFlip")) {
if (params$free$x) {
layout$SCALE_X <- seq_len(nrow(layout))
} else {
layout$SCALE_X <- 1L
}
if (params$free$y) {
layout$SCALE_Y <- seq_len(nrow(layout))
} else {
layout$SCALE_Y <- 1L
}
# Switch the scales back
layout[c("SCALE_X", "SCALE_Y")] <- layout[c("SCALE_Y", "SCALE_X")]
}

panel_order <- order(layout$ROW, layout$COL)
Expand Down
21 changes: 12 additions & 9 deletions R/geom-.R
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,13 @@ Geom <- ggproto("Geom",
themed_defaults <- eval_from_theme(default_aes, theme)
default_aes[names(themed_defaults)] <- themed_defaults

# Mark staged/scaled defaults as modifier (#6135)
delayed <- is_scaled_aes(default_aes) | is_staged_aes(default_aes)
if (any(delayed)) {
modifiers <- defaults(modifiers, default_aes[delayed])
default_aes <- default_aes[!delayed]
}

missing_eval <- lapply(default_aes, eval_tidy)
# Needed for geoms with defaults set to NULL (e.g. GeomSf)
missing_eval <- compact(missing_eval)
Expand All @@ -157,12 +164,10 @@ Geom <- ggproto("Geom",
# This order means that they will have access to all default aesthetics
if (length(modifiers) != 0) {
# Set up evaluation environment
env <- child_env(baseenv(), after_scale = after_scale)
# Mask stage with stage_scaled so it returns the correct expression
stage_mask <- child_env(emptyenv(), stage = stage_scaled)
mask <- new_data_mask(as_environment(data, stage_mask), stage_mask)
mask$.data <- as_data_pronoun(mask)
modified_aes <- lapply(substitute_aes(modifiers), eval_tidy, mask, env)
modified_aes <- eval_aesthetics(
substitute_aes(modifiers), data,
mask = list(stage = stage_scaled)
)

# Check that all output are valid data
nondata_modified <- check_nondata_cols(modified_aes)
Expand All @@ -177,11 +182,9 @@ Geom <- ggproto("Geom",
))
}

names(modified_aes) <- names(rename_aes(modifiers))

modified_aes <- cleanup_mismatched_data(modified_aes, nrow(data), "after_scale")

modified_aes <- data_frame0(!!!compact(modified_aes))
modified_aes <- data_frame0(!!!modified_aes)

data <- data_frame0(!!!defaults(modified_aes, data))
}
Expand Down
12 changes: 11 additions & 1 deletion R/geom-defaults.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,17 @@
#' @keywords internal
#' @note
#' Please note that geom defaults can be set *en masse* via the `theme(geom)`
#' argument.
#' argument. The guidelines for when to use which function are as follows:
#'
#' * If you want to change defaults for all geoms in all plots, use
#' `theme_update(geom = element_geom(...))`.
#' * If you want to change defaults for all geoms in a single plot, use
#' `+ theme(geom = element_geom(...))`.
#' * If you want to change defaults for one geom in all plots, use
#' `update_geom_defaults()`.
#' * If you want to change settings for one geom in a single plot, use fixed
#' aesthetic parameters in a layer, like so: `geom_point(colour = "red")`.
#'
#' @export
#' @examples
#'
Expand Down
18 changes: 18 additions & 0 deletions R/geom-histogram.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
#' one change at a time. You may need to look at a few options to uncover
#' the full story behind your data.
#'
#' By default, the _height_ of the bars represent the counts within each bin.
#' However, there are situations where this behavior might produce misleading
#' plots (e.g., when non-equal-width bins are used), in which case it might be
#' preferable to have the _area_ of the bars represent the counts (by setting
#' `aes(y = after_stat(count / width))`). See example below.
#'
#' In addition to `geom_histogram()`, you can create a histogram plot by using
#' `scale_x_binned()` with [geom_bar()]. This method by default plots tick marks
#' in between each bar.
Expand Down Expand Up @@ -63,6 +69,18 @@
#' ggplot(diamonds, aes(price, after_stat(density), colour = cut)) +
#' geom_freqpoly(binwidth = 500)
#'
#'
#' # When using the non-equal-width bins, we should set the area of the bars to
#' # represent the counts (not the height).
#' # Here we're using 10 equi-probable bins:
#' price_bins <- quantile(diamonds$price, probs = seq(0, 1, length = 11))
#'
#' ggplot(diamonds, aes(price)) +
#' geom_histogram(breaks = price_bins, color = "black") # misleading (height = count)
#'
#' ggplot(diamonds, aes(price, after_stat(count / width))) +
#' geom_histogram(breaks = price_bins, color = "black") # area = count
#'
#' if (require("ggplot2movies")) {
#' # Often we don't want the height of the bar to represent the
#' # count of observations, but the sum of some other variable.
Expand Down
2 changes: 1 addition & 1 deletion R/geom-map.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ NULL
#' # how `geom_map()` works. It requires two data frames:
#' # One contains the coordinates of each polygon (`positions`), and is
#' # provided via the `map` argument. The other contains the
#' # other the values associated with each polygon (`values`). An id
#' # values associated with each polygon (`values`). An id
#' # variable links the two together.
#'
#' ids <- factor(c("1.1", "2.1", "1.2", "2.2", "1.3", "2.3"))
Expand Down
3 changes: 2 additions & 1 deletion R/geom-sf.R
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,8 @@ GeomSf <- ggproto("GeomSf", Geom,
linewidth[is_point] <- stroke[is_point]

gp <- gpar(
col = colour, fill = fill, fontsize = font_size, lwd = linewidth,
col = colour, fill = fill, fontsize = font_size,
lwd = linewidth, lty = data$linetype,
lineend = lineend, linejoin = linejoin, linemitre = linemitre
)

Expand Down
2 changes: 1 addition & 1 deletion R/guide-.R
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ Guide <- ggproto(
# Renders tickmarks
build_ticks = function(key, elements, params, position = params$position,
length = elements$ticks_length) {
if (!is.element(elements)) {
if (!is.theme_element(elements)) {
elements <- elements$ticks
}
if (!inherits(elements, "element_line")) {
Expand Down
Loading

0 comments on commit d731ace

Please sign in to comment.