Skip to content

Commit d60d716

Browse files
authored
Merge branch 'main' into rect_key
2 parents 1d9443c + 2478406 commit d60d716

Some content is hidden

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

59 files changed

+1395
-393
lines changed

DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Imports:
3535
cli,
3636
grDevices,
3737
grid,
38-
gtable (>= 0.1.1),
38+
gtable (>= 0.3.6),
3939
isoband,
4040
lifecycle (> 1.0.1),
4141
rlang (>= 1.1.0),
@@ -247,6 +247,7 @@ Collate:
247247
'stat-bindot.R'
248248
'stat-binhex.R'
249249
'stat-boxplot.R'
250+
'stat-connect.R'
250251
'stat-contour.R'
251252
'stat-count.R'
252253
'stat-density-2d.R'

NAMESPACE

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ S3method("[[",ggproto)
1313
S3method("[[<-",uneval)
1414
S3method(.DollarNames,ggproto)
1515
S3method(as.data.frame,mapped_discrete)
16+
S3method(as.gtable,ggplot)
17+
S3method(as.gtable,ggplot_built)
1618
S3method(as.list,ggproto)
1719
S3method(autolayer,default)
1820
S3method(autoplot,default)
@@ -257,6 +259,7 @@ export(StatBin2d)
257259
export(StatBindot)
258260
export(StatBinhex)
259261
export(StatBoxplot)
262+
export(StatConnect)
260263
export(StatContour)
261264
export(StatContourFilled)
262265
export(StatCount)
@@ -684,6 +687,7 @@ export(stat_bin_2d)
684687
export(stat_bin_hex)
685688
export(stat_binhex)
686689
export(stat_boxplot)
690+
export(stat_connect)
687691
export(stat_contour)
688692
export(stat_contour_filled)
689693
export(stat_count)

NEWS.md

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

3+
* `position_fill()` avoids stacking observations of zero (@teunbrand, #6338)
4+
* New `layer(layout)` argument to interact with facets (@teunbrand, #3062)
5+
* New `stat_connect()` to connect points via steps or other shapes
6+
(@teunbrand, #6228)
37
* Fixed regression with incorrectly drawn gridlines when using `coord_flip()`
48
(@teunbrand, #6293).
59
* Deprecated functions and arguments prior to ggplot2 3.0.0 throw errors instead
@@ -249,8 +253,8 @@
249253
and (non-text) margins inherit from (@teunbrand, #5622).
250254
* `geom_ribbon()` can have varying `fill` or `alpha` in linear coordinate
251255
systems (@teunbrand, #4690).
252-
* `geom_tile()` computes default widths and heights per panel instead of
253-
per layer (@teunbrand, #5740).
256+
* `geom_tile()` and `position_jitter()` computes default widths and heights
257+
per panel instead of per layer (@teunbrand, #5740, #3722).
254258
* The `fill` of the `panel.border` theme setting is ignored and forced to be
255259
transparent (#5782).
256260
* `stat_align()` skips computation when there is only 1 group and therefore
@@ -321,6 +325,8 @@
321325
(@teunbrand, #3669).
322326
* Added `scale_{x/y}_time(date_breaks, date_minor_breaks, date_labels)`
323327
(@teunbrand, #4335).
328+
* (internal) `legend.key.width` and `legend.key.height` calculations are no
329+
longer precomputed before guides are drawn (@teunbrand, #6339)
324330
* `ggsave()` can write a multi-page pdf file when provided with a list of plots
325331
(@teunbrand, #5093).
326332
* (internal) When `validate_subclass()` fails to find a class directly, it tries
@@ -329,6 +335,11 @@
329335
copying trained position scales (#3441).
330336
* `draw_key_rect()` replaces a `NA` fill by the `colour` aesthetic and
331337
`draw_key_polygon()` has 0 linewidth as internal default (@teunbrand, #5385).
338+
* Improved consistency of curve direction in `geom_curve()` (@teunbrand, #5069)
339+
* `linetype = NA` is now interpreted to mean 'no line' instead of raising errors
340+
(@teunbrand, #6269).
341+
* The default colour and fill scales have a new `palette` argument
342+
(@teunbrand, #6064).
332343

333344
# ggplot2 3.5.1
334345

R/facet-.R

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,3 +872,95 @@ censor_labels <- function(ranges, layout, labels) {
872872
}
873873
ranges
874874
}
875+
876+
map_facet_data <- function(data, layout, params) {
877+
878+
if (empty(data)) {
879+
return(vec_cbind(data %|W|% NULL, PANEL = integer(0)))
880+
}
881+
882+
vars <- params$facet %||% c(params$rows, params$cols)
883+
884+
if (length(vars) == 0) {
885+
data$PANEL <- layout$PANEL
886+
return(data)
887+
}
888+
889+
grid_layout <- all(c("rows", "cols") %in% names(params))
890+
layer_layout <- attr(data, "layout")
891+
if (identical(layer_layout, "fixed")) {
892+
n <- vec_size(data)
893+
data <- vec_rep(data, vec_size(layout))
894+
data$PANEL <- vec_rep_each(layout$PANEL, n)
895+
return(data)
896+
}
897+
898+
# Compute faceting values
899+
facet_vals <- eval_facets(vars, data, params$.possible_columns)
900+
901+
include_margins <- !isFALSE(params$margin %||% FALSE) &&
902+
nrow(facet_vals) == nrow(data) && grid_layout
903+
if (include_margins) {
904+
# Margins are computed on evaluated faceting values (#1864).
905+
facet_vals <- reshape_add_margins(
906+
vec_cbind(facet_vals, .index = seq_len(nrow(facet_vals))),
907+
list(intersect(names(params$rows), names(facet_vals)),
908+
intersect(names(params$cols), names(facet_vals))),
909+
params$margins %||% FALSE
910+
)
911+
# Apply recycling on original data to fit margins
912+
# We're using base subsetting here because `data` might have a superclass
913+
# that isn't handled well by vctrs::vec_slice
914+
data <- data[facet_vals$.index, , drop = FALSE]
915+
facet_vals$.index <- NULL
916+
}
917+
918+
# If we need to fix rows or columns, we make the corresponding faceting
919+
# variables missing on purpose
920+
if (grid_layout) {
921+
if (identical(layer_layout, "fixed_rows")) {
922+
facet_vals <- facet_vals[setdiff(names(facet_vals), names(params$cols))]
923+
}
924+
if (identical(layer_layout, "fixed_cols")) {
925+
facet_vals <- facet_vals[setdiff(names(facet_vals), names(params$rows))]
926+
}
927+
}
928+
929+
# If any faceting variables are missing, add them in by
930+
# duplicating the data
931+
missing_facets <- setdiff(names(vars), names(facet_vals))
932+
if (length(missing_facets) > 0) {
933+
934+
to_add <- unique0(layout[missing_facets])
935+
936+
data_rep <- rep.int(seq_len(nrow(data)), nrow(to_add))
937+
facet_rep <- rep(seq_len(nrow(to_add)), each = nrow(data))
938+
939+
data <- unrowname(data[data_rep, , drop = FALSE])
940+
facet_vals <- unrowname(vec_cbind(
941+
unrowname(facet_vals[data_rep, , drop = FALSE]),
942+
unrowname(to_add[facet_rep, , drop = FALSE])
943+
))
944+
}
945+
946+
if (nrow(facet_vals) < 1) {
947+
# Add PANEL variable
948+
data$PANEL <- NO_PANEL
949+
return(data)
950+
}
951+
952+
facet_vals[] <- lapply(facet_vals, as_unordered_factor)
953+
facet_vals[] <- lapply(facet_vals, addNA, ifany = TRUE)
954+
layout[] <- lapply(layout, as_unordered_factor)
955+
956+
# Add PANEL variable
957+
keys <- join_keys(facet_vals, layout, by = names(vars))
958+
data$PANEL <- layout$PANEL[match(keys$x, keys$y)]
959+
960+
# Filter panels when layer_layout is an integer
961+
if (is_integerish(layer_layout)) {
962+
data <- vec_slice(data, data$PANEL %in% layer_layout)
963+
}
964+
965+
data
966+
}

R/facet-grid-.R

Lines changed: 12 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ NULL
6969
#' labels and the interior axes get none. When `"all_x"` or `"all_y"`, only
7070
#' draws the labels at the interior axes in the x- or y-direction
7171
#' respectively.
72+
#'
73+
#' @section Layer layout:
74+
#' The [`layer(layout)`][layer()] argument in context of `facet_grid()` can take
75+
#' the following values:
76+
#' * `NULL` (default) to use the faceting variables to assign panels.
77+
#' * An integer vector to include selected panels. Panel numbers not included in
78+
#' the integer vector are excluded.
79+
#' * `"fixed"` to repeat data across every panel.
80+
#' * `"fixed_rows"` to repeat data across rows.
81+
#' * `"fixed_cols"` to repeat data across columns.
82+
#'
7283
#' @export
7384
#' @seealso
7485
#' The `r link_book("facet grid section", "facet#facet-grid")`
@@ -282,69 +293,8 @@ FacetGrid <- ggproto("FacetGrid", Facet,
282293

283294
panels
284295
},
285-
map_data = function(data, layout, params) {
286-
if (empty(data)) {
287-
return(vec_cbind(data %|W|% NULL, PANEL = integer(0)))
288-
}
289-
290-
rows <- params$rows
291-
cols <- params$cols
292-
vars <- c(names(rows), names(cols))
293-
294-
if (length(vars) == 0) {
295-
data$PANEL <- layout$PANEL
296-
return(data)
297-
}
298-
299-
# Compute faceting values
300-
facet_vals <- eval_facets(c(rows, cols), data, params$.possible_columns)
301-
if (nrow(facet_vals) == nrow(data)) {
302-
# Margins are computed on evaluated faceting values (#1864).
303-
facet_vals <- reshape_add_margins(
304-
# We add an index column to track data recycling
305-
vec_cbind(facet_vals, .index = seq_len(nrow(facet_vals))),
306-
list(intersect(names(rows), names(facet_vals)),
307-
intersect(names(cols), names(facet_vals))),
308-
params$margins
309-
)
310-
# Apply recycling on original data to fit margins
311-
# We're using base subsetting here because `data` might have a superclass
312-
# that isn't handled well by vctrs::vec_slice
313-
data <- data[facet_vals$.index, , drop = FALSE]
314-
facet_vals$.index <- NULL
315-
}
316296

317-
# If any faceting variables are missing, add them in by
318-
# duplicating the data
319-
missing_facets <- setdiff(vars, names(facet_vals))
320-
if (length(missing_facets) > 0) {
321-
to_add <- unique0(layout[missing_facets])
322-
323-
data_rep <- rep.int(seq_len(nrow(data)), nrow(to_add))
324-
facet_rep <- rep(seq_len(nrow(to_add)), each = nrow(data))
325-
326-
data <- unrowname(data[data_rep, , drop = FALSE])
327-
facet_vals <- unrowname(vec_cbind(
328-
unrowname(facet_vals[data_rep, , drop = FALSE]),
329-
unrowname(to_add[facet_rep, , drop = FALSE]))
330-
)
331-
}
332-
333-
# Add PANEL variable
334-
if (nrow(facet_vals) == 0) {
335-
# Special case of no faceting
336-
data$PANEL <- NO_PANEL
337-
} else {
338-
facet_vals[] <- lapply(facet_vals[], as_unordered_factor)
339-
facet_vals[] <- lapply(facet_vals[], addNA, ifany = TRUE)
340-
layout[] <- lapply(layout[], as_unordered_factor)
341-
342-
keys <- join_keys(facet_vals, layout, by = vars)
343-
344-
data$PANEL <- layout$PANEL[match(keys$x, keys$y)]
345-
}
346-
data
347-
},
297+
map_data = map_facet_data,
348298

349299
attach_axes = function(table, layout, ranges, coord, theme, params) {
350300

R/facet-null.R

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ NULL
66
#' @inheritParams facet_grid
77
#' @keywords internal
88
#' @export
9+
#' @section Layer layout:
10+
#' The [`layer(layout)`][layer()] argument in context of `facet_null()` is
11+
#' completely ignored.
912
#' @examples
1013
#' # facet_null is the default faceting specification if you
1114
#' # don't override it with facet_grid or facet_wrap

R/facet-wrap.R

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ NULL
4545
#' the exterior axes get labels, and the interior axes get none. When
4646
#' `"all_x"` or `"all_y"`, only draws the labels at the interior axes in the
4747
#' x- or y-direction respectively.
48+
#'
49+
#' @section Layer layout:
50+
#' The [`layer(layout)`][layer()] argument in context of `facet_wrap()` can take
51+
#' the following values:
52+
#' * `NULL` (default) to use the faceting variables to assign panels.
53+
#' * An integer vector to include selected panels. Panel numbers not included in
54+
#' the integer vector are excluded.
55+
#' * `"fixed"` to repeat data across every panel.
56+
#'
4857
#' @inheritParams facet_grid
4958
#' @seealso
5059
#' The `r link_book("facet wrap section", "facet#sec-facet-wrap")`
@@ -247,42 +256,8 @@ FacetWrap <- ggproto("FacetWrap", Facet,
247256

248257
panels
249258
},
250-
map_data = function(data, layout, params) {
251-
if (empty(data)) {
252-
return(vec_cbind(data %|W|% NULL, PANEL = integer(0)))
253-
}
254-
255-
vars <- params$facets
256-
257-
if (length(vars) == 0) {
258-
data$PANEL <- layout$PANEL
259-
return(data)
260-
}
261-
262-
facet_vals <- eval_facets(vars, data, params$.possible_columns)
263-
facet_vals[] <- lapply(facet_vals[], as_unordered_factor)
264-
layout[] <- lapply(layout[], as_unordered_factor)
265259

266-
missing_facets <- setdiff(names(vars), names(facet_vals))
267-
if (length(missing_facets) > 0) {
268-
269-
to_add <- unique0(layout[missing_facets])
270-
271-
data_rep <- rep.int(seq_len(nrow(data)), nrow(to_add))
272-
facet_rep <- rep(seq_len(nrow(to_add)), each = nrow(data))
273-
274-
data <- data[data_rep, , drop = FALSE]
275-
facet_vals <- vec_cbind(
276-
facet_vals[data_rep, , drop = FALSE],
277-
to_add[facet_rep, , drop = FALSE]
278-
)
279-
}
280-
281-
keys <- join_keys(facet_vals, layout, by = names(vars))
282-
283-
data$PANEL <- layout$PANEL[match(keys$x, keys$y)]
284-
data
285-
},
260+
map_data = map_facet_data,
286261

287262
attach_axes = function(table, layout, ranges, coord, theme, params) {
288263

R/geom-curve.R

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ GeomCurve <- ggproto("GeomCurve", GeomSegment,
5555

5656
trans <- coord$transform(data, panel_params)
5757

58+
flip <- flip_curve(trans, coord, panel_params)
59+
if (flip) {
60+
trans <- rename(trans, c(x = "xend", xend = "x", y = "yend", yend = "y"))
61+
if (!is.null(arrow)) {
62+
# Flip end where arrow appears (2 = last, 1 = first, 3 = both)
63+
arrow$ends <- match(arrow$ends, c(2, 1, 3))
64+
}
65+
}
66+
5867
arrow.fill <- arrow.fill %||% trans$colour
5968

6069
curveGrob(
@@ -72,3 +81,41 @@ GeomCurve <- ggproto("GeomCurve", GeomSegment,
7281
)
7382
}
7483
)
84+
85+
# Helper function for determining whether curves should swap segment ends to
86+
# keep curvature consistent over transformations
87+
flip_curve <- function(data, coord, params) {
88+
flip <- FALSE
89+
90+
# Figure implicit flipping transformations in coords
91+
if (inherits(coord, "CoordFlip")) {
92+
flip <- !flip
93+
} else if (inherits(coord, "CoordTrans")) {
94+
if (identical(coord$trans$x$name, "reverse")) {
95+
flip <- !flip
96+
}
97+
if (identical(coord$trans$y$name, "reverse")) {
98+
flip <- !flip
99+
}
100+
}
101+
102+
# We don't flip when none or both directions are reversed
103+
if ((coord$reverse %||% "none") %in% c("x", "y")) {
104+
flip <- !flip
105+
}
106+
107+
# Check scales for reverse transforms
108+
# Note that polar coords do not have x/y scales, but these are unsupported
109+
# anyway
110+
fn <- params$x$get_transformation
111+
if (is.function(fn) && identical(fn()$name, "reverse")) {
112+
flip <- !flip
113+
}
114+
115+
fn <- params$y$get_transformation
116+
if (is.function(fn) && identical(fn()$name, "reverse")) {
117+
flip <- !flip
118+
}
119+
120+
flip
121+
}

0 commit comments

Comments
 (0)