Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ggplot2 3.5.0 #5592

Merged
merged 49 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
a99cb82
Increment version number to 3.5.0
teunbrand Dec 18, 2023
d6e45d6
Fix note (#5594)
teunbrand Dec 18, 2023
fe9d5bd
ingest plain patterns as lists in `layer()` (#5595)
teunbrand Dec 18, 2023
38c8796
`<AsIs>` never invokes identity scale (#5597)
teunbrand Dec 18, 2023
29ce30a
Bugfix `guide_axis_theta()` label size (#5598)
teunbrand Dec 19, 2023
ed4971e
flip justification along with angle (#5600)
teunbrand Dec 19, 2023
2f2633c
Run revdepcheck
thomasp85 Dec 21, 2023
954e2f4
Missing `Scale$get_transformation()` (#5607)
teunbrand Dec 22, 2023
1b142f9
swap `vec_in()` for `%in%` (#5606)
teunbrand Dec 22, 2023
f15a332
explicitly ignore empty arguments (#5604)
teunbrand Dec 22, 2023
9d1d9c6
Fix partial match in deprecated guide arguments (#5603)
teunbrand Dec 22, 2023
49d7a8d
Guide custom theme (#5602)
teunbrand Dec 22, 2023
c700dc8
Protection for position scale's `call` parameter (#5605)
teunbrand Dec 22, 2023
3c571b1
fix misplaced parenthesis
teunbrand Dec 22, 2023
63cfa5e
update revdepcheck
thomasp85 Dec 22, 2023
47b4bd0
propagate spacing (#5615)
teunbrand Jan 4, 2024
0ee63c3
Text key justification (#5618)
teunbrand Jan 4, 2024
9c15f81
adhere to strip placement even if the axis is empty (#5630)
thomasp85 Jan 5, 2024
78125e0
Set `vjust = 1` for `axis.title.y.right`. (#5629)
teunbrand Jan 5, 2024
358325d
Revert renaming `Scale$trans` to `Scale$transformation` (#5626)
teunbrand Jan 8, 2024
0c992dc
unclass raster data before calculating resolution (#5638)
teunbrand Jan 12, 2024
8cbc148
remove censoring date breaks (#5636)
teunbrand Jan 12, 2024
dad3573
put deprecated arg last (#5635)
teunbrand Jan 12, 2024
c834279
fill potentially missing args (#5634)
teunbrand Jan 12, 2024
5bfecd2
drop empty panels from bar width calculation (#5633)
teunbrand Jan 12, 2024
75d3197
redocument
teunbrand Jan 12, 2024
e1fb4a3
another revdepcheck
thomasp85 Jan 15, 2024
26de56e
setup parameters before declaring key (#5643)
teunbrand Jan 16, 2024
2d1f31c
Do not make more than 10k points for a line (#5644)
teunbrand Jan 16, 2024
d5c2f1f
Drop `zeroGrob()` guides (#5645)
teunbrand Jan 16, 2024
61f9a0a
Only throw scale training errors when the Range class is the expected…
teunbrand Jan 18, 2024
6afb5d7
Change legend tick length inheritance (#5652)
teunbrand Jan 19, 2024
7a4af1e
Don't strip classes in `Geom$use_defaults()` (#5657)
teunbrand Jan 23, 2024
5c550e7
Simplify legend layout logic (#5648)
teunbrand Jan 25, 2024
3d5e9d2
Add missing `element_grob()`
teunbrand Jan 25, 2024
87abade
Balance geom label whitespace (#5663)
teunbrand Jan 26, 2024
617c336
Restore `legend.byrow` (#5662)
teunbrand Jan 26, 2024
fa6d68d
redo revdepcheck
thomasp85 Feb 5, 2024
7378156
Radial inner radius (#5679)
teunbrand Feb 12, 2024
0e4394d
discard empty colourbar (#5681)
teunbrand Feb 12, 2024
9e67b94
revert 5657, instead explicitly restore AsIs (#5683)
teunbrand Feb 12, 2024
9f2b8ba
rerun revdepcheck
thomasp85 Feb 12, 2024
389315e
theta/r guides get theta/r theme elements (#5680)
teunbrand Feb 13, 2024
6836936
add section about guide extensions (#5693)
teunbrand Feb 20, 2024
9592cd6
one more rerun
thomasp85 Feb 21, 2024
7e63435
update copyright
thomasp85 Feb 21, 2024
a6f1a7c
update cran-comments
thomasp85 Feb 21, 2024
3aa80aa
Increment version number to 3.5.0.9000
thomasp85 Feb 23, 2024
eaaabbf
Add blog post link
thomasp85 Feb 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: ggplot2
Version: 3.4.4.9000
Version: 3.5.0.9000
Title: Create Elegant Data Visualisations Using the Grammar of Graphics
Authors@R: c(
person("Hadley", "Wickham", , "hadley@posit.co", role = "aut",
Expand Down Expand Up @@ -79,7 +79,7 @@ Config/testthat/edition: 3
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
RoxygenNote: 7.3.0
Collate:
'ggproto.R'
'ggplot-global.R'
Expand Down
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
YEAR: 2020
COPYRIGHT HOLDER: ggplot2 authors
YEAR: 2024
COPYRIGHT HOLDER: ggplot2 core developer team
4 changes: 3 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ S3method(print,ggproto_method)
S3method(print,rel)
S3method(print,theme)
S3method(print,uneval)
S3method(scale_type,AsIs)
S3method(scale_type,Date)
S3method(scale_type,POSIXt)
S3method(scale_type,character)
Expand Down Expand Up @@ -719,7 +718,10 @@ import(scales)
import(vctrs)
importFrom(glue,glue)
importFrom(glue,glue_collapse)
importFrom(grid,arrow)
importFrom(grid,unit)
importFrom(lifecycle,deprecated)
importFrom(scales,alpha)
importFrom(stats,setNames)
importFrom(tibble,tibble)
importFrom(utils,.DollarNames)
Expand Down
8 changes: 6 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# ggplot2 (development version)

# ggplot2 3.5.0

This is a minor release that turned out quite beefy. It is focused on
overhauling the guide system: the system responsible for displaying information
from scales in the guise of axes and legends. As part of that overhaul, new
Expand Down Expand Up @@ -53,8 +55,7 @@ vectors interact with the scale system, namely: not at all.
* The `trans` argument in scales and secondary axes has been renamed to
`transform`. The `trans` argument itself is deprecated. To access the
transformation from the scale, a new `get_transformation()` method is
added to Scale-classes that retrieves the transformation object from the
new `Scale$transformation` field (#5558).
added to Scale-classes (#5558).

* Providing a numeric vector to `theme(legend.position)` has been deprecated.
To set the default legend position inside the plot use
Expand Down Expand Up @@ -137,6 +138,9 @@ stats, facets and coords (#3329, @teunbrand)
`guides(x = guide_axis(position = "top"))` will display the title at the
top by default (#4650).

* The default `vjust` for the `axis.title.y.right` element is now 1 instead of
0.

* Unknown secondary axis guide positions are now inferred as the opposite
of the primary axis guide when the latter has a known `position` (#4650).

Expand Down
18 changes: 9 additions & 9 deletions R/axis-secondary.R
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ sec_axis <- function(transform = NULL,

transform <- as_function(transform)
ggproto(NULL, AxisSecondary,
transform = transform,
trans = transform,
name = name,
breaks = breaks,
labels = labels,
Expand All @@ -119,8 +119,8 @@ sec_axis <- function(transform = NULL,
#' @rdname sec_axis
#'
#' @export
dup_axis <- function(transform = ~., trans = deprecated(),
name = derive(), breaks = derive(), labels = derive(), guide = derive()) {
dup_axis <- function(transform = ~., name = derive(), breaks = derive(),
labels = derive(), guide = derive(), trans = deprecated()) {
sec_axis(transform, trans = trans, name, breaks, labels, guide)
}

Expand Down Expand Up @@ -153,7 +153,7 @@ is.derived <- function(x) {
#' @usage NULL
#' @export
AxisSecondary <- ggproto("AxisSecondary", NULL,
transform = NULL,
trans = NULL,
axis = NULL,
name = waiver(),
breaks = waiver(),
Expand All @@ -165,27 +165,27 @@ AxisSecondary <- ggproto("AxisSecondary", NULL,
detail = 1000,

empty = function(self) {
is.null(self$transform %||% self$trans)
is.null(self$trans)
},

# Inherit settings from the primary axis/scale
init = function(self, scale) {
if (self$empty()) {
return()
}
transform <- self$transform %||% self$trans
transform <- self$trans
if (!is.function(transform)) {
cli::cli_abort("Transformation for secondary axes must be a function.")
}
if (is.derived(self$name) && !is.waive(scale$name)) self$name <- scale$name
if (is.derived(self$breaks)) self$breaks <- scale$breaks
if (is.waive(self$breaks)) self$breaks <- scale$transformation$breaks
if (is.waive(self$breaks)) self$breaks <- scale$get_transformation()$breaks
if (is.derived(self$labels)) self$labels <- scale$labels
if (is.derived(self$guide)) self$guide <- scale$guide
},

transform_range = function(self, range) {
self$transform(range)
self$trans(range)
},

mono_test = function(self, scale){
Expand Down Expand Up @@ -299,7 +299,7 @@ AxisSecondary <- ggproto("AxisSecondary", NULL,
labels = self$labels,
limits = range,
expand = c(0, 0),
transformation = transformation
trans = transformation
)
scale$train(range)
scale
Expand Down
2 changes: 1 addition & 1 deletion R/coord-munch.R
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ munch_data <- function(data, dist = NULL, segment_length = 0.01) {
}

# How many endpoints for each old segment, not counting the last one
extra <- pmax(floor(dist / segment_length), 1)
extra <- pmin(pmax(floor(dist / segment_length), 1), 1e4)
extra[is.na(extra)] <- 1
# Generate extra pieces for x and y values
# The final point must be manually inserted at the end
Expand Down
69 changes: 46 additions & 23 deletions R/coord-radial.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,30 @@
#' in accordance with the computed `theta` position. If `FALSE` (default),
#' no such transformation is performed. Can be useful to rotate text geoms in
#' alignment with the coordinates.
#' @param donut A `numeric` between 0 and 1 setting the size of a donut hole.
#' @param inner.radius A `numeric` between 0 and 1 setting the size of a inner.radius hole.
#'
#' @note
#' In `coord_radial()`, position guides are can be defined by using
#' `guides(r = ..., theta = ..., r.sec = ..., theta.sec = ...)`. Note that
#' these guides require `r` and `theta` as available aesthetics. The classic
#' `guide_axis()` can be used for the `r` positions and `guide_axis_theta()` can
#' be used for the `theta` positions. Using the `theta.sec` position is only
#' sensible when `donut > 0`.
#' sensible when `inner.radius > 0`.
#'
#' @export
#' @examples
#' # A partial polar plot
#' ggplot(mtcars, aes(disp, mpg)) +
#' geom_point() +
#' coord_radial(start = -0.4 * pi, end = 0.4 * pi, donut = 0.3)
#' coord_radial(start = -0.4 * pi, end = 0.4 * pi, inner.radius = 0.3)
coord_radial <- function(theta = "x",
start = 0, end = NULL,
expand = TRUE,
direction = 1,
clip = "off",
r_axis_inside = NULL,
rotate_angle = FALSE,
donut = 0) {
inner.radius = 0) {

theta <- arg_match0(theta, c("x", "y"))
r <- if (theta == "x") "y" else "x"
Expand All @@ -47,7 +47,7 @@ coord_radial <- function(theta = "x",
check_bool(rotate_angle)
check_number_decimal(start, allow_infinite = FALSE)
check_number_decimal(end, allow_infinite = FALSE, allow_null = TRUE)
check_number_decimal(donut, min = 0, max = 1, allow_infinite = FALSE)
check_number_decimal(inner.radius, min = 0, max = 1, allow_infinite = FALSE)

end <- end %||% (start + 2 * pi)
if (start > end) {
Expand All @@ -64,7 +64,7 @@ coord_radial <- function(theta = "x",
direction = sign(direction),
r_axis_inside = r_axis_inside,
rotate_angle = rotate_angle,
donut = c(donut, 1) * 0.4,
inner_radius = c(inner.radius, 1) * 0.4,
clip = clip
)
}
Expand All @@ -84,13 +84,13 @@ CoordRadial <- ggproto("CoordRadial", Coord,
distance = function(self, x, y, details) {
arc <- details$arc %||% c(0, 2 * pi)
if (self$theta == "x") {
r <- rescale(y, from = details$r.range, to = self$donut / 0.4)
r <- rescale(y, from = details$r.range, to = self$inner_radius / 0.4)
theta <- theta_rescale_no_clip(
x, details$theta.range,
arc, self$direction
)
} else {
r <- rescale(x, from = details$r.range, to = self$donut / 0.4)
r <- rescale(x, from = details$r.range, to = self$inner_radius / 0.4)
theta <- theta_rescale_no_clip(
y, details$theta.range,
arc, self$direction
Expand All @@ -117,8 +117,8 @@ CoordRadial <- ggproto("CoordRadial", Coord,
c(
view_scales_polar(scale_x, self$theta, expand = self$expand),
view_scales_polar(scale_y, self$theta, expand = self$expand),
list(bbox = polar_bbox(self$arc, donut = self$donut),
arc = self$arc, donut = self$donut)
list(bbox = polar_bbox(self$arc, inner_radius = self$inner_radius),
arc = self$arc, inner_radius = self$inner_radius)
)
},

Expand Down Expand Up @@ -215,6 +215,12 @@ CoordRadial <- ggproto("CoordRadial", Coord,
gdefs[[r]] <- guides[[r]]$get_layer_key(gdefs[[r]], layers)
}

# Set theme suffixes
gdefs$theta$theme_suffix <- "theta"
gdefs$theta.sec$theme_suffix <- "theta"
gdefs$r$theme_suffix <- "r"
gdefs$r.sec$theme_suffix <- "r"

panel_params$guides$update_params(gdefs)
panel_params
},
Expand All @@ -224,7 +230,7 @@ CoordRadial <- ggproto("CoordRadial", Coord,
bbox <- panel_params$bbox %||% list(x = c(0, 1), y = c(0, 1))
arc <- panel_params$arc %||% c(0, 2 * pi)

data$r <- r_rescale(data$r, panel_params$r.range, panel_params$donut)
data$r <- r_rescale(data$r, panel_params$r.range, panel_params$inner_radius)
data$theta <- theta_rescale(
data$theta, panel_params$theta.range,
arc, self$direction
Expand All @@ -233,7 +239,7 @@ CoordRadial <- ggproto("CoordRadial", Coord,
data$y <- rescale(data$r * cos(data$theta) + 0.5, from = bbox$y)

if (self$rotate_angle && "angle" %in% names(data)) {
data$angle <- flip_text_angle(data$angle - rad2deg(data$theta))
data <- flip_data_text_angle(data)
}

data
Expand All @@ -258,7 +264,7 @@ CoordRadial <- ggproto("CoordRadial", Coord,
bbox <- panel_params$bbox %||% list(x = c(0, 1), y = c(0, 1))
arc <- panel_params$arc %||% c(0, 2 * pi)
dir <- self$direction
donut <- panel_params$donut
inner_radius <- panel_params$inner_radius

theta_lim <- panel_params$theta.range
theta_maj <- panel_params$theta.major
Expand All @@ -273,7 +279,7 @@ CoordRadial <- ggproto("CoordRadial", Coord,
theta_fine <- seq(self$arc[1], self$arc[2], length.out = 100)

r_fine <- r_rescale(panel_params$r.major, panel_params$r.range,
panel_params$donut)
panel_params$inner_radius)

# This gets the proper theme element for theta and r grid lines:
# panel.grid.major.x or .y
Expand Down Expand Up @@ -308,8 +314,8 @@ CoordRadial <- ggproto("CoordRadial", Coord,

ggname("grill", grobTree(
background,
theta_grid(theta_maj, grid_elems[[1]], donut, bbox),
theta_grid(theta_min, grid_elems[[2]], donut, bbox),
theta_grid(theta_maj, grid_elems[[1]], inner_radius, bbox),
theta_grid(theta_min, grid_elems[[2]], inner_radius, bbox),
element_render(
theme, majorr, name = "radius",
x = rescale(rep(r_fine, each = length(theta_fine)) *
Expand Down Expand Up @@ -453,7 +459,7 @@ view_scales_polar <- function(scale, theta = "x", expand = TRUE) {
#' @examples
#' polar_bbox(c(0, 1) * pi)
polar_bbox <- function(arc, margin = c(0.05, 0.05, 0.05, 0.05),
donut = c(0, 0.4)) {
inner_radius = c(0, 0.4)) {

# Early exit if we have full circle or more
if (abs(diff(arc)) >= 2 * pi) {
Expand All @@ -463,8 +469,8 @@ polar_bbox <- function(arc, margin = c(0.05, 0.05, 0.05, 0.05),
# X and Y position of the sector arc ends
xmax <- 0.5 * sin(arc) + 0.5
ymax <- 0.5 * cos(arc) + 0.5
xmin <- donut[1] * sin(arc) + 0.5
ymin <- donut[1] * cos(arc) + 0.5
xmin <- inner_radius[1] * sin(arc) + 0.5
ymin <- inner_radius[1] * cos(arc) + 0.5

margin <- c(
max(ymin) + margin[1],
Expand Down Expand Up @@ -528,17 +534,34 @@ flip_text_angle <- function(angle) {
angle
}

flip_data_text_angle <- function(data) {
if (!all(c("angle", "theta") %in% names(data))) {
return(data)
}
angle <- (data$angle - rad2deg(data$theta)) %% 360
flip <- angle > 90 & angle < 270
angle[flip] <- angle[flip] + 180
data$angle <- angle
if ("hjust" %in% names(data)) {
data$hjust[flip] <- 1 - data$hjust[flip]
}
if ("vjust" %in% names(data)) {
data$vjust[flip] <- 1 - data$vjust[flip]
}
data
}


theta_grid <- function(theta, element, donut = c(0, 0.4),
theta_grid <- function(theta, element, inner_radius = c(0, 0.4),
bbox = list(x = c(0, 1), y = c(0, 1))) {
n <- length(theta)
if (n < 1) {
return(NULL)
}

donut <- rep(donut, n)
x <- rep(sin(theta), each = 2) * donut + 0.5
y <- rep(cos(theta), each = 2) * donut + 0.5
inner_radius <- rep(inner_radius, n)
x <- rep(sin(theta), each = 2) * inner_radius + 0.5
y <- rep(cos(theta), each = 2) * inner_radius + 0.5

element_grob(
element,
Expand Down
Loading
Loading