Skip to content

Commit 628d7ab

Browse files
authored
Standardise width calculation (#6065)
* helper for computing size * use helper * add news bullet
1 parent 1803552 commit 628d7ab

File tree

8 files changed

+83
-34
lines changed

8 files changed

+83
-34
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@
252252
* `geom_abline()` clips to the panel range in the vertical direction too
253253
(@teunbrand, #6086).
254254
* Added `panel.widths` and `panel.heights` to `theme()` (#5338, @teunbrand).
255+
* Standardised the calculation of `width`, which are now implemented as
256+
aesthetics (@teunbrand, #2800).
255257

256258
# ggplot2 3.5.1
257259

R/geom-bar.R

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ GeomBar <- ggproto("GeomBar", GeomRect,
130130
# limits, not just those for which x and y are outside the limits
131131
non_missing_aes = c("xmin", "xmax", "ymin", "ymax"),
132132

133-
default_aes = aes(!!!GeomRect$default_aes, width = NULL),
133+
default_aes = aes(!!!GeomRect$default_aes, width = 0.9),
134134

135135
setup_params = function(data, params) {
136136
params$flipped_aes <- has_flipped_aes(data, params)
@@ -139,14 +139,13 @@ GeomBar <- ggproto("GeomBar", GeomRect,
139139

140140
extra_params = c("just", "na.rm", "orientation"),
141141

142-
setup_data = function(data, params) {
142+
setup_data = function(self, data, params) {
143143
data$flipped_aes <- params$flipped_aes
144144
data <- flip_data(data, params$flipped_aes)
145-
data$width <- data$width %||%
146-
params$width %||% (min(vapply(
147-
split(data$x, data$PANEL, drop = TRUE),
148-
resolution, numeric(1), zero = FALSE
149-
)) * 0.9)
145+
data <- compute_data_size(
146+
data, size = params$width,
147+
default = self$default_aes$width, zero = FALSE
148+
)
150149
data$just <- params$just %||% 0.5
151150
data <- transform(data,
152151
ymin = pmin(y, 0), ymax = pmax(y, 0),

R/geom-boxplot.R

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -236,21 +236,21 @@ geom_boxplot <- function(mapping = NULL, data = NULL,
236236
#' @export
237237
GeomBoxplot <- ggproto("GeomBoxplot", Geom,
238238

239-
# need to declare `width` here in case this geom is used with a stat that
240-
# doesn't have a `width` parameter (e.g., `stat_identity`).
241-
extra_params = c("na.rm", "width", "orientation", "outliers"),
239+
extra_params = c("na.rm", "orientation", "outliers"),
242240

243241
setup_params = function(data, params) {
244242
params$flipped_aes <- has_flipped_aes(data, params)
245243
params
246244
},
247245

248-
setup_data = function(data, params) {
246+
setup_data = function(self, data, params) {
249247
data$flipped_aes <- params$flipped_aes
250248
data <- flip_data(data, params$flipped_aes)
251-
data$width <- data$width %||%
252-
params$width %||% (resolution(data$x, FALSE, TRUE) * 0.9)
253-
249+
data <- compute_data_size(
250+
data, params$width,
251+
default = self$default_aes$width,
252+
zero = FALSE, discrete = TRUE
253+
)
254254
if (isFALSE(params$outliers)) {
255255
data$outliers <- NULL
256256
}
@@ -389,7 +389,8 @@ GeomBoxplot <- ggproto("GeomBoxplot", Geom,
389389
weight = 1, colour = from_theme(col_mix(ink, paper, 0.2)),
390390
fill = from_theme(paper), size = from_theme(pointsize),
391391
alpha = NA, shape = from_theme(pointshape), linetype = from_theme(bordertype),
392-
linewidth = from_theme(borderwidth)
392+
linewidth = from_theme(borderwidth),
393+
width = 0.9
393394
),
394395

395396
required_aes = c("x|y", "lower|xlower", "upper|xupper", "middle|xmiddle", "ymin|xmin", "ymax|xmax"),

R/geom-dotplot.R

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,16 @@ GeomDotplot <- ggproto("GeomDotplot", Geom,
194194
alpha = NA,
195195
stroke = from_theme(borderwidth * 2),
196196
linetype = from_theme(linetype),
197-
weight = 1
197+
weight = 1,
198+
width = 0.9
198199
),
199200

200-
setup_data = function(data, params) {
201-
data$width <- data$width %||%
202-
params$width %||% (resolution(data$x, FALSE, TRUE) * 0.9)
201+
setup_data = function(self, data, params) {
202+
data <- compute_data_size(
203+
data, params$width,
204+
default = self$default_aes$width,
205+
zero = FALSE, discrete = TRUE
206+
)
203207

204208
# Set up the stacking function and range
205209
if (is.null(params$stackdir) || params$stackdir == "up") {

R/geom-errorbar.R

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ GeomErrorbar <- ggproto("GeomErrorbar", Geom,
6262
colour = from_theme(ink),
6363
linewidth = from_theme(linewidth),
6464
linetype = from_theme(linetype),
65-
width = 0.5,
65+
width = 0.9,
6666
alpha = NA
6767
),
6868

@@ -76,17 +76,21 @@ GeomErrorbar <- ggproto("GeomErrorbar", Geom,
7676

7777
extra_params = c("na.rm", "orientation"),
7878

79-
setup_data = function(data, params) {
79+
setup_data = function(self, data, params) {
8080
data$flipped_aes <- params$flipped_aes
8181
data <- flip_data(data, params$flipped_aes)
82-
data$width <- data$width %||%
83-
params$width %||% (resolution(data$x, FALSE, TRUE) * 0.9)
82+
data <- compute_data_size(
83+
data, params$width,
84+
default = self$default_aes$width,
85+
zero = FALSE, discrete = TRUE
86+
)
8487
data <- transform(data,
8588
xmin = x - width / 2, xmax = x + width / 2, width = NULL
8689
)
8790
flip_data(data, params$flipped_aes)
8891
},
8992

93+
# Note: `width` is vestigial
9094
draw_panel = function(self, data, panel_params, coord, lineend = "butt",
9195
width = NULL, flipped_aes = FALSE) {
9296
data <- check_linewidth(data, snake_class(self))

R/geom-tile.R

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,20 @@ geom_tile <- function(mapping = NULL, data = NULL,
109109
GeomTile <- ggproto("GeomTile", GeomRect,
110110
extra_params = c("na.rm"),
111111

112-
setup_data = function(data, params) {
113-
114-
data$width <- data$width %||% params$width %||%
115-
stats::ave(data$x, data$PANEL, FUN = function(x) resolution(x, FALSE, TRUE))
116-
data$height <- data$height %||% params$height %||%
117-
stats::ave(data$y, data$PANEL, FUN = function(y) resolution(y, FALSE, TRUE))
112+
setup_data = function(self, data, params) {
118113

114+
data <- compute_data_size(
115+
data, params$width,
116+
default = self$default_aes$width,
117+
panels = "by", target = "width",
118+
zero = FALSE, discrete = TRUE
119+
)
120+
data <- compute_data_size(
121+
data, params$height,
122+
default = self$default_aes$height,
123+
panels = "by", target = "height",
124+
zero = FALSE, discrete = TRUE
125+
)
119126
transform(data,
120127
xmin = x - width / 2, xmax = x + width / 2, width = NULL,
121128
ymin = y - height / 2, ymax = y + height / 2, height = NULL
@@ -127,7 +134,7 @@ GeomTile <- ggproto("GeomTile", GeomRect,
127134
colour = NA,
128135
linewidth = from_theme(0.4 * borderwidth),
129136
linetype = from_theme(bordertype),
130-
alpha = NA, width = NA, height = NA
137+
alpha = NA, width = 1, height = 1
131138
),
132139

133140
required_aes = c("x", "y"),

R/geom-violin.R

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,13 @@ GeomViolin <- ggproto("GeomViolin", Geom,
131131

132132
extra_params = c("na.rm", "orientation", "lineend", "linejoin", "linemitre"),
133133

134-
setup_data = function(data, params) {
134+
setup_data = function(self, data, params) {
135135
data$flipped_aes <- params$flipped_aes
136136
data <- flip_data(data, params$flipped_aes)
137-
data$width <- data$width %||%
138-
params$width %||% (resolution(data$x, FALSE, TRUE) * 0.9)
137+
data <- compute_data_size(
138+
data, params$width,
139+
default = self$default_aes$width
140+
)
139141
# ymin, ymax, xmin, and xmax define the bounding rectangle for each group
140142
data <- dapply(data, "group", transform,
141143
xmin = x - width / 2,
@@ -203,7 +205,8 @@ GeomViolin <- ggproto("GeomViolin", Geom,
203205
fill = from_theme(paper),
204206
linewidth = from_theme(borderwidth),
205207
linetype = from_theme(bordertype),
206-
alpha = NA
208+
alpha = NA,
209+
width = 0.9
207210
),
208211

209212
required_aes = c("x", "y"),

R/utilities.R

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,3 +909,32 @@ prompt_install <- function(pkg, reason = NULL) {
909909
utils::install.packages(pkg)
910910
is_installed(pkg)
911911
}
912+
913+
compute_data_size <- function(data, size, default = 0.9,
914+
target = "width",
915+
panels = c("across", "by", "ignore"),
916+
...) {
917+
918+
data[[target]] <- data[[target]] %||% size
919+
if (!is.null(data[[target]])) {
920+
return(data)
921+
}
922+
923+
var <- if (target == "height") "y" else "x"
924+
panels <- arg_match0(panels, c("across", "by", "ignore"))
925+
926+
if (panels == "across") {
927+
res <- split(data[[var]], data$PANEL, drop = FALSE)
928+
res <- vapply(res, resolution, FUN.VALUE = numeric(1), ...)
929+
res <- min(res, na.rm = TRUE)
930+
} else if (panels == "by") {
931+
res <- ave(data[[var]], data$PANEL, FUN = function(x) resolution(x, ...))
932+
} else {
933+
res <- resolution(data[[var]], ...)
934+
}
935+
if (is_quosure(default)) {
936+
default <- eval_tidy(default, data = data)
937+
}
938+
data[[target]] <- res * (default %||% 0.9)
939+
data
940+
}

0 commit comments

Comments
 (0)