Skip to content

Commit 4fd167d

Browse files
committed
resolve merge conflict
Merge branch 'main' into sanitise_bins # Conflicts: # man/ggplot2-ggproto.Rd
2 parents b08c93d + 73b4119 commit 4fd167d

15 files changed

+479
-25
lines changed

DESCRIPTION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ Collate:
255255
'stat-ellipse.R'
256256
'stat-function.R'
257257
'stat-identity.R'
258+
'stat-manual.R'
258259
'stat-qq-line.R'
259260
'stat-qq.R'
260261
'stat-quantilemethods.R'

NAMESPACE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ export(StatEcdf)
265265
export(StatEllipse)
266266
export(StatFunction)
267267
export(StatIdentity)
268+
export(StatManual)
268269
export(StatQq)
269270
export(StatQqLine)
270271
export(StatQuantile)
@@ -691,6 +692,7 @@ export(stat_ecdf)
691692
export(stat_ellipse)
692693
export(stat_function)
693694
export(stat_identity)
695+
export(stat_manual)
694696
export(stat_qq)
695697
export(stat_qq_line)
696698
export(stat_quantile)

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# ggplot2 (development version)
22

3+
* New stat: `stat_manual()` for arbitrary computations (@teunbrand, #3501)
34
* Reversal of a dimension, typically 'x' or 'y', is now controlled by the
45
`reverse` argument in `coord_cartesian()`, `coord_fixed()`, `coord_radial()`
56
and `coord_sf()`. In `coord_radial()`, this replaces the older `direction`
@@ -237,6 +238,7 @@
237238
(@teunbrand, #4722, #6069).
238239
* `geom_abline()` clips to the panel range in the vertical direction too
239240
(@teunbrand, #6086).
241+
* Added `panel.widths` and `panel.heights` to `theme()` (#5338, @teunbrand).
240242

241243
# ggplot2 3.5.1
242244

R/facet-.R

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,53 @@ Facet <- ggproto("Facet", NULL,
263263
},
264264
format_strip_labels = function(layout, params) {
265265
return()
266+
},
267+
set_panel_size = function(table, theme) {
268+
269+
new_widths <- calc_element("panel.widths", theme)
270+
new_heights <- calc_element("panel.heights", theme)
271+
272+
if (is.null(new_widths) && is.null(new_heights)) {
273+
return(table)
274+
}
275+
276+
if (isTRUE(table$respect)) {
277+
args <- !c(is.null(new_widths), is.null(new_heights))
278+
args <- c("panel.widths", "panel.heights")[args]
279+
cli::cli_warn(
280+
"Aspect ratios are overruled by {.arg {args}} theme element{?s}."
281+
)
282+
table$respect <- FALSE
283+
}
284+
285+
rows <- panel_rows(table)
286+
cols <- panel_cols(table)
287+
288+
if (length(new_widths) == 1L && nrow(cols) > 1L) {
289+
# Get total size of non-panel widths in between panels
290+
extra <- setdiff(seq(min(cols$l), max(cols$r)), union(cols$l, cols$r))
291+
extra <- unit(sum(width_cm(table$widths[extra])), "cm")
292+
# Distribute width proportionally
293+
relative <- as.numeric(table$widths[cols$l]) # assumed to be simple units
294+
new_widths <- (new_widths - extra) * (relative / sum(relative))
295+
}
296+
if (!is.null(new_widths)) {
297+
table$widths[cols$l] <- rep(new_widths, length.out = nrow(cols))
298+
}
299+
300+
if (length(new_heights) == 1L && nrow(rows) > 1L) {
301+
# Get total size of non-panel heights in between panels
302+
extra <- setdiff(seq(min(rows$t), max(rows$t)), union(rows$t, rows$b))
303+
extra <- unit(sum(height_cm(table$heights[extra])), "cm")
304+
# Distribute height proportionally
305+
relative <- as.numeric(table$heights[rows$t]) # assumed to be simple units
306+
new_heights <- (new_heights - extra) * (relative / sum(relative))
307+
}
308+
if (!is.null(new_heights)) {
309+
table$heights[rows$t] <- rep(new_heights, length.out = nrow(rows))
310+
}
311+
312+
table
266313
}
267314
)
268315

R/layout.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ Layout <- ggproto("Layout", NULL,
9494
theme,
9595
self$facet_params
9696
)
97+
plot_table <- self$facet$set_panel_size(plot_table, theme)
9798

9899
# Draw individual labels, then add to gtable
99100
labels <- self$coord$labels(
@@ -300,7 +301,6 @@ Layout <- ggproto("Layout", NULL,
300301
}
301302
)
302303

303-
304304
# Helpers -----------------------------------------------------------------
305305

306306
# Function for applying scale method to multiple variables in a given

R/stat-manual.R

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
2+
#' Manually compute transformations
3+
#'
4+
#' `stat_manual()` takes a function that computes a data transformation for
5+
#' every group.
6+
#'
7+
#' @inheritParams layer
8+
#' @inheritParams geom_point
9+
#' @param fun Function that takes a data frame as input and returns a data
10+
#' frame or data frame-like list as output. The default (`identity()`) returns
11+
#' the data unchanged.
12+
#' @param args A list of arguments to pass to the function given in `fun`.
13+
#'
14+
#' @eval rd_aesthetics("stat", "manual")
15+
#' @section Aesthetics:
16+
#' Input aesthetics are determined by the `fun` argument. Output aesthetics must
17+
#' include those required by `geom`. Any aesthetic that is constant within a
18+
#' group will be preserved even if dropped by `fun`.
19+
#'
20+
#' @export
21+
#'
22+
#' @examples
23+
#' # A standard scatterplot
24+
#' p <- ggplot(mtcars, aes(disp, mpg, colour = factor(cyl))) +
25+
#' geom_point()
26+
#'
27+
#' # The default just displays points as-is
28+
#' p + stat_manual()
29+
#'
30+
#' # Using a custom function
31+
#' make_hull <- function(data) {
32+
#' hull <- chull(x = data$x, y = data$y)
33+
#' data.frame(x = data$x[hull], y = data$y[hull])
34+
#' }
35+
#'
36+
#' p + stat_manual(
37+
#' geom = "polygon",
38+
#' fun = make_hull,
39+
#' fill = NA
40+
#' )
41+
#'
42+
#' # Using the `with` function with quoting
43+
#' p + stat_manual(
44+
#' fun = with,
45+
#' args = list(expr = quote({
46+
#' hull <- chull(x, y)
47+
#' list(x = x[hull], y = y[hull])
48+
#' })),
49+
#' geom = "polygon", fill = NA
50+
#' )
51+
#'
52+
#' # Using the `transform` function with quoting
53+
#' p + stat_manual(
54+
#' geom = "segment",
55+
#' fun = transform,
56+
#' args = list(
57+
#' xend = quote(mean(x)),
58+
#' yend = quote(mean(y))
59+
#' )
60+
#' )
61+
#'
62+
#' # Using dplyr verbs with `vars()`
63+
#' if (requireNamespace("dplyr", quietly = TRUE)) {
64+
#'
65+
#' # Get centroids with `summarise()`
66+
#' p + stat_manual(
67+
#' size = 10, shape = 21,
68+
#' fun = dplyr::summarise,
69+
#' args = vars(x = mean(x), y = mean(y))
70+
#' )
71+
#'
72+
#' # Connect to centroid with `mutate`
73+
#' p + stat_manual(
74+
#' geom = "segment",
75+
#' fun = dplyr::mutate,
76+
#' args = vars(xend = mean(x), yend = mean(y))
77+
#' )
78+
#'
79+
#' # Computing hull with `reframe()`
80+
#' p + stat_manual(
81+
#' geom = "polygon", fill = NA,
82+
#' fun = dplyr::reframe,
83+
#' args = vars(hull = chull(x, y), x = x[hull], y = y[hull])
84+
#' )
85+
#' }
86+
stat_manual <- function(
87+
mapping = NULL,
88+
data = NULL,
89+
geom = "point",
90+
position = "identity",
91+
...,
92+
fun = identity,
93+
args = list(),
94+
na.rm = FALSE,
95+
show.legend = NA,
96+
inherit.aes = TRUE) {
97+
98+
layer(
99+
data = data,
100+
mapping = mapping,
101+
stat = StatManual,
102+
geom = geom,
103+
position = position,
104+
show.legend = show.legend,
105+
inherit.aes = inherit.aes,
106+
params = list2(
107+
na.rm = na.rm,
108+
fun = fun,
109+
args = args,
110+
...
111+
)
112+
)
113+
}
114+
115+
#' @rdname ggplot2-ggproto
116+
#' @format NULL
117+
#' @usage NULL
118+
#' @export
119+
StatManual <- ggproto(
120+
"StatManual", Stat,
121+
122+
setup_params = function(data, params) {
123+
params$fun <- allow_lambda(params$fun)
124+
check_function(params$fun, arg = "fun")
125+
params
126+
},
127+
128+
compute_group = function(data, scales, fun = identity, args = list()) {
129+
as_gg_data_frame(inject(fun(data, !!!args)))
130+
}
131+
)

R/theme-elements.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,8 @@ el_def <- function(class = NULL, inherit = NULL, description = NULL) {
639639
panel.grid.minor.x = el_def("element_line", "panel.grid.minor"),
640640
panel.grid.minor.y = el_def("element_line", "panel.grid.minor"),
641641
panel.ontop = el_def("logical"),
642+
panel.widths = el_def("unit"),
643+
panel.heights = el_def("unit"),
642644

643645
strip.background = el_def("element_rect", "rect"),
644646
strip.background.x = el_def("element_rect", "strip.background"),

R/theme.R

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@
143143
#' and x axis grid lines are vertical. `panel.grid.*.*` inherits from
144144
#' `panel.grid.*` which inherits from `panel.grid`, which in turn inherits
145145
#' from `line`
146+
#' @param panel.widths,panel.heights Sizes for panels (`units`). Can be a
147+
#' single unit to set the total size for the panel area, or a unit vector to
148+
#' set the size of individual panels.
146149
#' @param panel.ontop option to place the panel (background, gridlines) over
147150
#' the data layers (`logical`). Usually used with a transparent or blank
148151
#' `panel.background`.
@@ -427,6 +430,8 @@ theme <- function(...,
427430
panel.grid.minor.x,
428431
panel.grid.minor.y,
429432
panel.ontop,
433+
panel.widths,
434+
panel.heights,
430435
plot.background,
431436
plot.title,
432437
plot.title.position,

_pkgdown.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ reference:
6868
- stat_summary_bin
6969
- stat_unique
7070
- stat_sf_coordinates
71+
- stat_manual
7172
- after_stat
7273

7374
- subtitle: Position adjustment

man/geom_bin_2d.Rd

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)