Skip to content

Commit 0b348cd

Browse files
authored
Skip alignment/stacking when possible (#5789)
* skip alignment if there is just one group * add extra group to test * skip stacking if every x position is unique * add news bullets
1 parent d3adf17 commit 0b348cd

File tree

4 files changed

+24
-18
lines changed

4 files changed

+24
-18
lines changed

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@
4949
per layer (@teunbrand, #5740).
5050
* The `fill` of the `panel.border` theme setting is ignored and forced to be
5151
transparent (#5782).
52+
* `stat_align()` skips computation when there is only 1 group and therefore
53+
alignment is not necessary (#5788).
54+
* `position_stack()` skips computation when all `x` values are unique and
55+
therefore stacking is not necessary (#5788).
5256

5357
# ggplot2 3.5.1
5458

R/position-stack.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ PositionStack <- ggproto("PositionStack", Position,
187187
if (is.null(params$var)) {
188188
return(data)
189189
}
190+
if (!vec_duplicate_any(data$x)) {
191+
# Every x is unique, nothing to stack here
192+
return(flip_data(data, params$flipped_aes))
193+
}
190194

191195
negative <- data$ymax < 0
192196
negative[is.na(negative)] <- FALSE

R/stat-align.R

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,19 @@ StatAlign <- ggproto("StatAlign", Stat,
4040
if (empty(data)) {
4141
return(data_frame0())
4242
}
43-
43+
if (is_unique(data$group)) {
44+
return(data)
45+
}
4446
names <- flipped_names(flipped_aes)
4547
x <- data[[names$x]]
4648
y <- data[[names$y]]
4749

48-
if (is_unique(data$group)) {
49-
# No need for interpolation
50-
cross <- x[0]
51-
} else {
52-
# Find positions where 0 is crossed
53-
pivot <- vec_unrep(data_frame0(group = data$group, y = y < 0))
54-
group_ends <- cumsum(vec_unrep(pivot$key$group)$times)
55-
pivot <- cumsum(pivot$times)[-group_ends]
56-
cross <- -y[pivot] * (x[pivot + 1] - x[pivot]) /
57-
(y[pivot + 1] - y[pivot]) + x[pivot]
58-
}
50+
# Find positions where 0 is crossed
51+
pivot <- vec_unrep(data_frame0(group = data$group, y = y < 0))
52+
group_ends <- cumsum(vec_unrep(pivot$key$group)$times)
53+
pivot <- cumsum(pivot$times)[-group_ends]
54+
cross <- -y[pivot] * (x[pivot + 1] - x[pivot]) /
55+
(y[pivot + 1] - y[pivot]) + x[pivot]
5956

6057
unique_loc <- unique(sort(c(x, cross)))
6158
adjust <- diff(range(unique_loc, na.rm = TRUE)) * 0.001

tests/testthat/test-stat-align.R

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,20 @@ test_that("alignment adjusts per panel", {
4848
# data into account (#5227)
4949

5050
df <- data_frame0(
51-
x = c(0, 1, 1000, 1001),
52-
y = c(-1, 1, -1, 1),
53-
g = c("A", "A", "B", "B")
51+
x = c(0, 1, 1000, 1001, 0, 1, 1000, 1001),
52+
y = c(-1, 1, -1, 1, -1, 1, -1, 1),
53+
f = c("A", "A", "B", "B", "A", "A", "B", "B"),
54+
g = c("a", "a", "b", "b", "c", "c", "d", "d")
5455
)
55-
p <- ggplot(df, aes(x, y))
56+
p <- ggplot(df, aes(x, y, group = g))
5657

5758
# Here, x-range is large, so adjustment should be larger
58-
ld <- layer_data(p + geom_area(aes(fill = g)))
59+
ld <- layer_data(p + geom_area(aes(fill = f)))
5960
expect_equal(diff(ld$x[1:2]), 1/6, tolerance = 1e-4)
6061

6162
# Here, x-ranges are smaller, so adjustment should be smaller instead of
6263
# considering the data as a whole
63-
ld <- layer_data(p + geom_area() + facet_wrap(vars(g), scales = "free_x"))
64+
ld <- layer_data(p + geom_area() + facet_wrap(vars(f), scales = "free_x"))
6465
expect_equal(diff(ld$x[1:2]), 1e-3, tolerance = 1e-4)
6566

6667
})

0 commit comments

Comments
 (0)