Skip to content

Commit 9d9db39

Browse files
committed
Merge branch 'main' into contour_rotation
2 parents 0a5e256 + f220ded commit 9d9db39

File tree

387 files changed

+41969
-10110
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

387 files changed

+41969
-10110
lines changed

.github/workflows/R-CMD-check.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363
cache-version: 3
6464
extra-packages: >
6565
any::rcmdcheck,
66-
Hmisc=?ignore-before-r=4.1.0,
66+
Hmisc=?ignore-before-r=4.2.0,
6767
quantreg=?ignore-before-r=4.3.0
6868
needs: check
6969

DESCRIPTION

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: ggplot2
2-
Version: 3.5.1.9000
32
Title: Create Elegant Data Visualisations Using the Grammar of Graphics
3+
Version: 3.5.1.9000
44
Authors@R: c(
55
person("Hadley", "Wickham", , "[email protected]", role = "aut",
66
comment = c(ORCID = "0000-0003-4757-117X")),
@@ -30,7 +30,7 @@ License: MIT + file LICENSE
3030
URL: https://ggplot2.tidyverse.org, https://github.com/tidyverse/ggplot2
3131
BugReports: https://github.com/tidyverse/ggplot2/issues
3232
Depends:
33-
R (>= 3.5)
33+
R (>= 4.0)
3434
Imports:
3535
cli,
3636
grDevices,
@@ -39,11 +39,9 @@ Imports:
3939
isoband,
4040
lifecycle (> 1.0.1),
4141
MASS,
42-
mgcv,
4342
rlang (>= 1.1.0),
4443
scales (>= 1.3.0),
4544
stats,
46-
tibble,
4745
vctrs (>= 0.6.0),
4846
withr (>= 2.5.0)
4947
Suggests:
@@ -55,6 +53,7 @@ Suggests:
5553
knitr,
5654
mapproj,
5755
maps,
56+
mgcv,
5857
multcomp,
5958
munsell,
6059
nlme,
@@ -67,6 +66,7 @@ Suggests:
6766
sf (>= 0.7-3),
6867
svglite (>= 2.1.2),
6968
testthat (>= 3.1.5),
69+
tibble,
7070
vdiffr (>= 1.0.6),
7171
xml2
7272
Enhances:
@@ -75,6 +75,7 @@ VignetteBuilder:
7575
knitr
7676
Config/Needs/website: ggtext, tidyr, forcats, tidyverse/tidytemplate
7777
Config/testthat/edition: 3
78+
Config/usethis/last-upkeep: 2024-10-24
7879
Encoding: UTF-8
7980
LazyData: true
8081
Roxygen: list(markdown = TRUE)
@@ -276,7 +277,6 @@ Collate:
276277
'utilities-break.R'
277278
'utilities-grid.R'
278279
'utilities-help.R'
279-
'utilities-matrix.R'
280280
'utilities-patterns.R'
281281
'utilities-resolution.R'
282282
'utilities-tidy-eval.R'

LICENSE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# MIT License
22

3-
Copyright (c) 2020 ggplot2 authors
3+
Copyright (c) 2024 ggplot2 core developer team
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

NAMESPACE

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,6 @@ S3method(guide_train,default)
8484
S3method(guide_transform,default)
8585
S3method(heightDetails,titleGrob)
8686
S3method(heightDetails,zeroGrob)
87-
S3method(interleave,default)
88-
S3method(interleave,unit)
8987
S3method(limits,Date)
9088
S3method(limits,POSIXct)
9189
S3method(limits,POSIXlt)
@@ -126,8 +124,6 @@ S3method(scale_type,logical)
126124
S3method(scale_type,numeric)
127125
S3method(scale_type,ordered)
128126
S3method(scale_type,sfc)
129-
S3method(single_value,default)
130-
S3method(single_value,factor)
131127
S3method(summary,ggplot)
132128
S3method(vec_cast,character.mapped_discrete)
133129
S3method(vec_cast,double.mapped_discrete)
@@ -344,6 +340,7 @@ export(draw_key_vpath)
344340
export(dup_axis)
345341
export(el_def)
346342
export(element_blank)
343+
export(element_geom)
347344
export(element_grob)
348345
export(element_line)
349346
export(element_rect)
@@ -367,6 +364,7 @@ export(find_panel)
367364
export(flip_data)
368365
export(flipped_names)
369366
export(fortify)
367+
export(from_theme)
370368
export(geom_abline)
371369
export(geom_area)
372370
export(geom_bar)
@@ -422,7 +420,9 @@ export(geom_violin)
422420
export(geom_vline)
423421
export(get_alt_text)
424422
export(get_element_tree)
423+
export(get_geom_defaults)
425424
export(get_guide_data)
425+
export(get_labs)
426426
export(get_last_plot)
427427
export(get_layer_data)
428428
export(get_layer_grob)
@@ -460,10 +460,21 @@ export(guide_transform)
460460
export(guides)
461461
export(has_flipped_aes)
462462
export(is.Coord)
463+
export(is.coord)
463464
export(is.facet)
465+
export(is.geom)
464466
export(is.ggplot)
465467
export(is.ggproto)
468+
export(is.guide)
469+
export(is.guides)
470+
export(is.layer)
471+
export(is.mapping)
472+
export(is.margin)
473+
export(is.position)
474+
export(is.scale)
475+
export(is.stat)
466476
export(is.theme)
477+
export(is.theme_element)
467478
export(label_both)
468479
export(label_bquote)
469480
export(label_context)
@@ -513,6 +524,8 @@ export(remove_missing)
513524
export(render_axes)
514525
export(render_strips)
515526
export(replace_theme)
527+
export(reset_geom_defaults)
528+
export(reset_stat_defaults)
516529
export(reset_theme_settings)
517530
export(resolution)
518531
export(scale_alpha)
@@ -733,7 +746,6 @@ importFrom(grid,unit)
733746
importFrom(lifecycle,deprecated)
734747
importFrom(scales,alpha)
735748
importFrom(stats,setNames)
736-
importFrom(tibble,tibble)
737749
importFrom(utils,.DollarNames)
738750
importFrom(utils,head)
739751
importFrom(utils,tail)

NEWS.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,49 @@
22

33
* `geom_contour()` should be able to recognise a rotated grid of points
44
(@teunbrand, #4320)
5+
* `geom_boxplot()` gains additional arguments to style the colour, linetype and
6+
linewidths of the box, whiskers, median line and staples (@teunbrand, #5126)
7+
* (internal) Using `after_scale()` in the `Geom*$default_aes()` field is now
8+
evaluated in the context of data (@teunbrand, #6135)
9+
* Fixed bug where binned scales wouldn't simultaneously accept transformations
10+
and function-limits (@teunbrand, #6144).
11+
* Fixed bug where the `ggplot2::`-prefix did not work with `stage()`
12+
(@teunbrand, #6104).
13+
* New `get_labs()` function for retrieving completed plot labels
14+
(@teunbrand, #6008).
15+
* Built-in `theme_*()` functions now have `ink` and `paper` arguments to control
16+
foreground and background colours respectively (@teunbrand)
17+
* The `summary()` method for ggplots is now more terse about facets
18+
(@teunbrand, #5989).
19+
* `guide_bins()`, `guide_colourbar()` and `guide_coloursteps()` gain an `angle`
20+
argument to overrule theme settings, similar to `guide_axis(angle)`
21+
(@teunbrand, #4594).
22+
* `coord_*(expand)` can now take a logical vector to control expansion at any
23+
side of the panel (top, right, bottom, left) (@teunbrand, #6020)
24+
* (Breaking) The defaults for all geoms can be set at one in the theme.
25+
(@teunbrand based on pioneering work by @dpseidel, #2239)
26+
* A new `theme(geom)` argument is used to track these defaults.
27+
* The `element_geom()` function can be used to populate that argument.
28+
* The `from_theme()` function allows access to the theme default fields from
29+
inside the `aes()` function.
30+
* Passing empty unmapped aesthetics to layers raises a warning instead of
31+
throwing an error (@teunbrand, #6009).
32+
* Moved {mgcv} from Imports to Suggests (@teunbrand, #5986)
33+
* New `reset_geom_defaults()` and `reset_stat_defaults()` to restore all geom or
34+
stat default aesthetics at once (@teunbrand, #5975).
35+
* `facet_wrap()` can have `space = "free_x"` with 1-row layouts and
36+
`space = "free_y"` with 1-column layouts (@teunbrand)
37+
* Secondary axes respect `n.breaks` setting in continuous scales (@teunbrand, #4483).
38+
* Layers can have names (@teunbrand, #4066).
39+
* (internal) improvements to `pal_qualitative()` (@teunbrand, #5013)
40+
* `coord_radial(clip = "on")` clips to the panel area when the graphics device
41+
supports clipping paths (@teunbrand, #5952).
42+
* (internal) Panel clipping responsibility moved from Facet class to Coord
43+
class through new `Coord$draw_panel()` method.
44+
* `theme(strip.clip)` now defaults to `"on"` and is independent of Coord
45+
clipping (@teunbrand, 5952).
46+
* (internal) rearranged the code of `Facet$draw_panels()` method (@teunbrand).
47+
* Axis labels are now justified across facet panels (@teunbrand, #5820)
548
* Fixed bug in `stat_function()` so x-axis title now produced automatically
649
when no data added. (@phispu, #5647).
750
* geom_sf now accepts shape names (@sierrajohnson, #5808)
@@ -139,6 +182,17 @@
139182
(@teunbrand, #5938, #4327).
140183
* Fixed bug where empty discrete scales weren't recognised as such
141184
(@teunbrand, #5945).
185+
* (internal) The summary function of `stat_summary()` and `stat_summary_bin()`
186+
is setup once in total instead of once per group (@teunbrand, #5971)
187+
* `facet_grid(space = "free")` can now be combined with `coord_fixed()`
188+
(@teunbrand, #4584).
189+
* `theme_classic()` now has black ticks and text instead of dark gray. In
190+
addition, `theme_classic()`'s axis line end is `"square"` (@teunbrand, #5978).
191+
* {tibble} is now suggested instead of imported (@teunbrand, #5986)
192+
* The ellipsis argument is now checked in `fortify()`, `get_alt_text()`,
193+
`labs()` and several guides (@teunbrand, #3196).
194+
* `stat_summary_bin()` no longer ignores `width` parameter (@teunbrand, #4647).
195+
* Added `keep.zeroes` argument to `stat_bin()` (@teunbrand, #3449)
142196

143197
# ggplot2 3.5.1
144198

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

189244
# ggplot2 3.5.0
190245

R/aes-evaluation.R

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
#' Below follows an overview of the three stages of evaluation and how aesthetic
3333
#' evaluation can be controlled.
3434
#'
35-
#' ## Stage 1: direct input
35+
#' ## Stage 1: direct input at the start
3636
#' The default is to map at the beginning, using the layer data provided by
3737
#' the user. If you want to map directly from the layer data you should not do
3838
#' anything special. This is the only stage where the original layer data can
@@ -87,17 +87,19 @@
8787
#' ```
8888
#'
8989
#' ## Complex staging
90-
#' If you want to map the same aesthetic multiple times, e.g. map `x` to a
91-
#' data column for the stat, but remap it for the geom, you can use the
92-
#' `stage()` function to collect multiple mappings.
90+
#' Sometimes, you may want to map the same aesthetic multiple times, e.g. map
91+
#' `x` to a data column at the start for the layer stat, but remap it later to
92+
#' a variable from the stat transformation for the layer geom. The `stage()`
93+
#' function allows you to control multiple mappings for the same aesthetic
94+
#' across all three stages of evaluation.
9395
#'
9496
#' ```r
9597
#' # Use stage to modify the scaled fill
9698
#' ggplot(mpg, aes(class, hwy)) +
9799
#' geom_boxplot(aes(fill = stage(class, after_scale = alpha(fill, 0.4))))
98100
#'
99101
#' # Using data for computing summary, but placing label elsewhere.
100-
#' # Also, we're making our own computed variable to use for the label.
102+
#' # Also, we're making our own computed variables to use for the label.
101103
#' ggplot(mpg, aes(class, displ)) +
102104
#' geom_violin() +
103105
#' stat_summary(
@@ -109,6 +111,18 @@
109111
#' fun.data = ~ round(data.frame(mean = mean(.x), sd = sd(.x)), 2)
110112
#' )
111113
#' ```
114+
#'
115+
#' Conceptually, `aes(x)` is equivalent to `aes(stage(start = x))`, and
116+
#' `aes(after_stat(count))` is equivalent to `aes(stage(after_stat = count))`,
117+
#' and so on. `stage()` is most useful when at least two of its arguments are
118+
#' specified.
119+
#'
120+
#' ## Theme access
121+
#' The `from_theme()` function can be used to acces the [`element_geom()`]
122+
#' fields of the `theme(geom)` argument. Using `aes(colour = from_theme(ink))`
123+
#' and `aes(colour = from_theme(accent))` allows swapping between foreground and
124+
#' accent colours.
125+
#'
112126
#' @rdname aes_eval
113127
#' @name aes_eval
114128
#'
@@ -192,6 +206,13 @@ stat <- function(x) {
192206
after_scale <- function(x) {
193207
x
194208
}
209+
210+
#' @rdname aes_eval
211+
#' @export
212+
from_theme <- function(x) {
213+
x
214+
}
215+
195216
#' @rdname aes_eval
196217
#' @export
197218
stage <- function(start = NULL, after_stat = NULL, after_scale = NULL) {
@@ -205,12 +226,10 @@ stage_scaled <- function(start = NULL, after_stat = NULL, after_scale = NULL) {
205226
}
206227

207228
# Regex to determine if an identifier refers to a calculated aesthetic
229+
# The pattern includes ye olde '...var...' syntax, which was
230+
# deprecated in 3.4.0 in favour of `after_stat()`
208231
match_calculated_aes <- "^\\.\\.([a-zA-Z._]+)\\.\\.$"
209232

210-
is_dotted_var <- function(x) {
211-
grepl(match_calculated_aes, x)
212-
}
213-
214233
# Determine if aesthetic is calculated
215234
is_calculated_aes <- function(aesthetics, warn = FALSE) {
216235
vapply(aesthetics, is_calculated, warn = warn, logical(1), USE.NAMES = FALSE)
@@ -221,6 +240,9 @@ is_scaled_aes <- function(aesthetics) {
221240
is_staged_aes <- function(aesthetics) {
222241
vapply(aesthetics, is_staged, logical(1), USE.NAMES = FALSE)
223242
}
243+
is_themed_aes <- function(aesthetics) {
244+
vapply(aesthetics, is_themed, logical(1), USE.NAMES = FALSE)
245+
}
224246
is_calculated <- function(x, warn = FALSE) {
225247
if (is_call(get_expr(x), "after_stat")) {
226248
return(TRUE)
@@ -229,7 +251,8 @@ is_calculated <- function(x, warn = FALSE) {
229251
if (is.null(x) || is.atomic(x)) {
230252
FALSE
231253
} else if (is.symbol(x)) {
232-
res <- is_dotted_var(as.character(x))
254+
# Test if x is a dotted variable
255+
res <- grepl(match_calculated_aes, as.character(x))
233256
if (res && warn) {
234257
what <- I(paste0("The dot-dot notation (`", x, "`)"))
235258
var <- gsub(match_calculated_aes, "\\1", as.character(x))
@@ -263,6 +286,9 @@ is_scaled <- function(x) {
263286
is_staged <- function(x) {
264287
is_call(get_expr(x), "stage")
265288
}
289+
is_themed <- function(x) {
290+
is_call(get_expr(x), "from_theme")
291+
}
266292

267293
# Strip dots from expressions
268294
strip_dots <- function(expr, env, strip_pronoun = FALSE) {
@@ -313,7 +339,7 @@ strip_stage <- function(expr) {
313339
} else if (is_call(uq_expr, "stage")) {
314340
uq_expr <- call_match(uq_expr, stage)
315341
# Prefer stat mapping if present, otherwise original mapping (fallback to
316-
# scale mapping) but there should always be two arguments to stage()
342+
# scale mapping)
317343
uq_expr$after_stat %||% uq_expr$start %||% uq_expr$after_scale
318344
} else {
319345
expr
@@ -339,3 +365,39 @@ make_labels <- function(mapping) {
339365
}
340366
Map(default_label, names(mapping), mapping)
341367
}
368+
369+
eval_aesthetics <- function(aesthetics, data, mask = NULL) {
370+
371+
env <- child_env(base_env())
372+
373+
# Here we mask functions, often to replace `stage()` with context appropriate
374+
# functions `stage_calculated()`/`stage_scaled()`.
375+
if (length(mask) > 0) {
376+
aesthetics <- substitute_aes(aesthetics, mask_function, mask = mask)
377+
}
378+
379+
evaled <- lapply(aesthetics, eval_tidy, data = data, env = env)
380+
names(evaled) <- names(aesthetics)
381+
compact(rename_aes(evaled))
382+
}
383+
384+
# `mask` is a list of functions where `names(mask)` indicate names of functions
385+
# that need to be replaced, and `mask[[i]]` is the function to replace it
386+
# with.
387+
mask_function <- function(x, mask) {
388+
if (!is.call(x)) {
389+
return(x)
390+
}
391+
nms <- names(mask)
392+
x[-1] <- lapply(x[-1], mask_function, mask = mask)
393+
if (!is_call(x, nms)) {
394+
return(x)
395+
}
396+
for (nm in nms) {
397+
if (is_call(x, nm)) {
398+
x[[1]] <- mask[[nm]]
399+
return(x)
400+
}
401+
}
402+
}
403+

0 commit comments

Comments
 (0)