Skip to content

Commit 516cd30

Browse files
authored
Merge branch 'main' into missing_linewidth_scales
2 parents ddd6c67 + c9b85d6 commit 516cd30

File tree

10 files changed

+118
-48
lines changed

10 files changed

+118
-48
lines changed

NEWS.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22

33
* Added `scale_linewidth_manual()` and `scale_linewidth_identity()` to support
44
the `linewidth` aesthetic (@teunbrand, #5050).
5+
* Automatic breaks in `scale_*_binned()` should no longer be out-of-bounds,
6+
and automatic limits expand to include these (@teunbrand, #5095, #5100).
7+
* Renamed computed aesthetic in `stat_ecdf()` to `ecdf`, to prevent incorrect
8+
scale transformations (@teunbrand, #5113 and #5112).
9+
* Fixed misbehaviour of `draw_key_boxplot()` and `draw_key_crossbar()` with
10+
skewed key aspect ratio (@teunbrand, #5082).
511
* `scale_*_binned()` handles zero-range limits more gracefully (@teunbrand,
612
#5066)
713
* Binned scales are now compatible with `trans = "date"` and `trans = "time"`
814
(@teunbrand, #4217).
915
* `ggsave()` warns when multiple `filename`s are given, and only writes to the
10-
first file (@teunbrand, #5114).
16+
first file (@teunbrand, #5114)
1117
* Fixed a regression in `geom_hex()` where aesthetics were replicated across
1218
bins (@thomasp85, #5037 and #5044)
1319
* Fixed spurious warning when `weight` aesthetic was used in `stat_smooth()`

R/legend-draw.r

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -98,39 +98,58 @@ draw_key_blank <- function(data, params, size) {
9898
#' @export
9999
#' @rdname draw_key
100100
draw_key_boxplot <- function(data, params, size) {
101-
grobTree(
102-
linesGrob(0.5, c(0.1, 0.25)),
103-
linesGrob(0.5, c(0.75, 0.9)),
104-
rectGrob(height = 0.5, width = 0.75),
105-
linesGrob(c(0.125, 0.875), 0.5),
106-
gp = gpar(
107-
col = data$colour %||% "grey20",
108-
fill = alpha(data$fill %||% "white", data$alpha),
109-
lwd = (data$linewidth %||% 0.5) * .pt,
110-
lty = data$linetype %||% 1,
111-
lineend = params$lineend %||% "butt",
112-
linejoin = params$linejoin %||% "mitre"
113-
),
114-
vp = if (isTRUE(params$flipped_aes)) viewport(angle = -90)
101+
gp <- gpar(
102+
col = data$colour %||% "grey20",
103+
fill = alpha(data$fill %||% "white", data$alpha),
104+
lwd = (data$linewidth %||% 0.5) * .pt,
105+
lty = data$linetype %||% 1,
106+
lineend = params$lineend %||% "butt",
107+
linejoin = params$linejoin %||% "mitre"
115108
)
109+
110+
if (isTRUE(params$flipped_aes)) {
111+
grobTree(
112+
linesGrob(c(0.1, 0.25), 0.5),
113+
linesGrob(c(0.75, 0.9), 0.5),
114+
rectGrob(width = 0.5, height = 0.75),
115+
linesGrob(0.5, c(0.125, 0.875)),
116+
gp = gp
117+
)
118+
} else {
119+
grobTree(
120+
linesGrob(0.5, c(0.1, 0.25)),
121+
linesGrob(0.5, c(0.75, 0.9)),
122+
rectGrob(height = 0.5, width = 0.75),
123+
linesGrob(c(0.125, 0.875), 0.5),
124+
gp = gp
125+
)
126+
}
116127
}
117128

118129
#' @export
119130
#' @rdname draw_key
120131
draw_key_crossbar <- function(data, params, size) {
121-
grobTree(
122-
rectGrob(height = 0.5, width = 0.75),
123-
linesGrob(c(0.125, 0.875), 0.5),
124-
gp = gpar(
125-
col = data$colour %||% "grey20",
126-
fill = alpha(data$fill %||% "white", data$alpha),
127-
lwd = (data$linewidth %||% 0.5) * .pt,
128-
lty = data$linetype %||% 1,
129-
lineend = params$lineend %||% "butt",
130-
linejoin = params$linejoin %||% "mitre"
131-
),
132-
vp = if (isTRUE(params$flipped_aes)) viewport(angle = -90)
132+
gp <- gpar(
133+
col = data$colour %||% "grey20",
134+
fill = alpha(data$fill %||% "white", data$alpha),
135+
lwd = (data$linewidth %||% 0.5) * .pt,
136+
lty = data$linetype %||% 1,
137+
lineend = params$lineend %||% "butt",
138+
linejoin = params$linejoin %||% "mitre"
133139
)
140+
if (isTRUE(params$flipped_aes)) {
141+
grobTree(
142+
rectGrob(height = 0.75, width = 0.5),
143+
linesGrob(0.5, c(0.125, 0.875)),
144+
gp = gp
145+
)
146+
} else {
147+
grobTree(
148+
rectGrob(height = 0.5, width = 0.75),
149+
linesGrob(c(0.125, 0.875), 0.5),
150+
gp = gp
151+
)
152+
}
134153
}
135154

136155
#' @export

R/scale-.r

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,7 @@ ScaleBinned <- ggproto("ScaleBinned", Scale,
10771077
breaks <- seq(limits[1], limits[2], length.out = n.breaks + 2)
10781078
breaks <- breaks[-c(1, length(breaks))]
10791079
}
1080+
breaks <- oob_discard(breaks, limits)
10801081

10811082
# Ensure terminal bins are same width if limits not set
10821083
if (is.null(self$limits)) {

R/scale-binned.R

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ ScaleBinnedPosition <- ggproto("ScaleBinnedPosition", ScaleBinned,
7070

7171
map = function(self, x, limits = self$get_limits()) {
7272
breaks <- self$get_breaks(limits)
73+
limits <- self$get_limits() # get_breaks() may have updated this
7374
all_breaks <- unique0(sort(c(limits[1], breaks, limits[2])))
7475

7576
if (self$after.stat) {

R/stat-bin.r

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,6 @@ StatBin <- ggproto("StatBin", Stat,
123123
params$closed <- if (params$right) "right" else "left"
124124
params$right <- NULL
125125
}
126-
if (!is.null(params$width)) {
127-
deprecate_warn0("2.1.0", "stat_bin(width)", "geom_bar()")
128-
}
129126
if (!is.null(params$boundary) && !is.null(params$center)) {
130127
cli::cli_abort("Only one of {.arg boundary} and {.arg center} may be specified in {.fn {snake_class(self)}}.")
131128
}
@@ -146,8 +143,7 @@ StatBin <- ggproto("StatBin", Stat,
146143
breaks = NULL, flipped_aes = FALSE,
147144
# The following arguments are not used, but must
148145
# be listed so parameters are computed correctly
149-
origin = NULL, right = NULL, drop = NULL,
150-
width = NULL) {
146+
origin = NULL, right = NULL, drop = NULL) {
151147
x <- flipped_names(flipped_aes)$x
152148
if (!is.null(breaks)) {
153149
if (!scales[[x]]$is_discrete()) {

R/stat-ecdf.r

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#' @param pad If `TRUE`, pad the ecdf with additional points (-Inf, 0)
2222
#' and (Inf, 1)
2323
#' @eval rd_computed_vars(
24-
#' y = "Cumulative density corresponding to `x`."
24+
#' ecdf = "Cumulative density corresponding to `x`."
2525
#' )
2626
#' @export
2727
#' @examples
@@ -73,7 +73,7 @@ stat_ecdf <- function(mapping = NULL, data = NULL,
7373
StatEcdf <- ggproto("StatEcdf", Stat,
7474
required_aes = c("x|y"),
7575

76-
default_aes = aes(y = after_stat(y)),
76+
default_aes = aes(x = after_stat(ecdf), y = after_stat(ecdf)),
7777

7878
setup_params = function(self, data, params) {
7979
params$flipped_aes <- has_flipped_aes(data, params, main_is_orthogonal = FALSE, main_is_continuous = TRUE)
@@ -103,7 +103,7 @@ StatEcdf <- ggproto("StatEcdf", Stat,
103103

104104
df_ecdf <- data_frame0(
105105
x = x,
106-
y = data_ecdf,
106+
ecdf = data_ecdf,
107107
.size = length(x)
108108
)
109109
df_ecdf$flipped_aes <- flipped_aes

man/stat_ecdf.Rd

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

tests/testthat/_snaps/draw-key/horizontal-boxplot-and-crossbar.svg

Lines changed: 8 additions & 12 deletions
Loading

tests/testthat/test-scale-binned.R

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,45 @@ test_that("binned scales only support continuous data", {
55
expect_snapshot_error(ggplot_build(p))
66
})
77

8+
test_that("binned scales limits can expand to fit breaks", {
9+
# See also #5095
10+
11+
scale <- scale_x_binned(right = FALSE, show.limits = TRUE)
12+
scale$train(c(14, 29))
13+
14+
limits <- scale$get_limits()
15+
breaks <- scale$get_breaks()
16+
new_limits <- scale$get_limits()
17+
18+
# Positive control
19+
expect_equal(limits, c(14, 29))
20+
# Test case, should have been updated in break calculation
21+
expect_equal(new_limits, c(14, 30))
22+
23+
# Negative control
24+
# Now, new limits should not be updated because limits were given instead
25+
# of computed
26+
scale <- scale_x_binned(right = FALSE, show.limits = TRUE,
27+
limits = c(14, 29))
28+
limits <- scale$get_limits()
29+
breaks <- scale$get_breaks()
30+
new_limits <- scale$get_limits()
31+
32+
expect_equal(limits, new_limits)
33+
})
34+
35+
test_that("binned limits should not compute out-of-bounds breaks", {
36+
scale <- scale_x_binned(n.breaks = 10)
37+
scale$train(c(1, 9))
38+
39+
limits <- scale$get_limits()
40+
breaks <- scale$get_breaks()
41+
expect_length(breaks, 7) # Not the requested 10 due to oob discarding
42+
expect_true(all(
43+
breaks > limits[1] & breaks < limits[2]
44+
))
45+
})
46+
847
test_that('binned scales can calculate breaks on dates', {
948

1049
data <- seq(as.Date("2000-01-01"), as.Date("2020-01-01"), length.out = 100)

tests/testthat/test-stat-ecdf.R

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,15 @@ test_that("stat_ecdf works in both directions", {
1515
expect_snapshot_error(ggplot_build(p))
1616
})
1717

18+
# See #5113 and #5112
19+
test_that("stat_ecdf responds to axis transformations", {
20+
n <- 4
21+
answer <- c(seq(0, 1, length.out = n + 1), 1)
22+
p <- ggplot(data_frame0(x = seq_len(n)), aes(x)) + stat_ecdf()
23+
24+
ld <- layer_data(p)
25+
expect_equal(ld$y, answer)
26+
27+
ld <- layer_data(p + scale_y_sqrt())
28+
expect_equal(ld$y, sqrt(answer))
29+
})

0 commit comments

Comments
 (0)