Skip to content

Commit 5ce5cf7

Browse files
authored
Fix misalignment in geom_dotplot when stackratio != 1 and stackdir != "up" (#4734)
Fixes #4614
1 parent d699fb1 commit 5ce5cf7

File tree

5 files changed

+107
-4
lines changed

5 files changed

+107
-4
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@
6464
* Updated documentation for `geom_contour()` to correctly reflect argument
6565
precedence between `bins` and `binwidth`. (@eliocamp, #4651)
6666

67+
* Dots in `geom_dotplot()` are now correctly aligned to the baseline when
68+
`stackratio != 1` and `stackdir != "up"` (@mjskay, #4614)
6769

6870
# ggplot2 3.3.5
6971
This is a very small release focusing on fixing a couple of untenable issues

R/geom-dotplot.r

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ GeomDotplot <- ggproto("GeomDotplot", Geom,
288288

289289
ggname("geom_dotplot",
290290
dotstackGrob(stackaxis = stackaxis, x = tdata$x, y = tdata$y, dotdia = dotdianpc,
291-
stackposition = tdata$stackpos, stackratio = stackratio,
291+
stackposition = tdata$stackpos, stackdir = stackdir, stackratio = stackratio,
292292
default.units = "npc",
293293
gp = gpar(col = alpha(tdata$colour, tdata$alpha),
294294
fill = alpha(tdata$fill, tdata$alpha),

R/grob-dotstack.r

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ dotstackGrob <- function(
44
stackaxis = "y",
55
dotdia = unit(1, "npc"), # Dot diameter in the non-stack axis, should be in npc
66
stackposition = 0, # Position of each dot in the stack, relative to origin
7+
stackdir = "up", # Stacking direction ("up", "down", "center", or "centerwhole")
78
stackratio = 1, # Stacking height of dots (.75 means 25% dot overlap)
89
default.units = "npc", name = NULL, gp = gpar(), vp = NULL)
910
{
@@ -17,7 +18,7 @@ dotstackGrob <- function(
1718
warn("Unit type of dotdia should be 'npc'")
1819

1920
grob(x = x, y = y, stackaxis = stackaxis, dotdia = dotdia,
20-
stackposition = stackposition, stackratio = stackratio,
21+
stackposition = stackposition, stackdir = stackdir, stackratio = stackratio,
2122
name = name, gp = gp, vp = vp, cl = "dotstackGrob")
2223
}
2324
# Only cross-version reliable way to check the unit of a unit object
@@ -31,14 +32,27 @@ makeContext.dotstackGrob <- function(x, recording = TRUE) {
3132
xmm <- convertX(x$x, "mm", valueOnly = TRUE)
3233
ymm <- convertY(x$y, "mm", valueOnly = TRUE)
3334

35+
# When stacking up (or down), stackratios != 1 will cause the bottom (top)
36+
# edge of the first dot in a stack to no longer touch the origin, as
37+
# stackpositions are expanded or contracted away from the dotstack's origin.
38+
# The stackoffset corrects that misalignment so that the first dot just
39+
# touches the dotstack's origin.
40+
if (is.null(x$stackdir) || x$stackdir == "up") {
41+
stackoffset <- (1 - x$stackratio) / 2
42+
} else if (x$stackdir == "down") {
43+
stackoffset <- -(1 - x$stackratio) / 2
44+
} else {
45+
stackoffset <- 0
46+
}
47+
3448
if (x$stackaxis == "x") {
3549
dotdiamm <- convertY(x$dotdia, "mm", valueOnly = TRUE)
36-
xpos <- xmm + dotdiamm * (x$stackposition * x$stackratio + (1 - x$stackratio) / 2)
50+
xpos <- xmm + dotdiamm * (x$stackposition * x$stackratio + stackoffset)
3751
ypos <- ymm
3852
} else if (x$stackaxis == "y") {
3953
dotdiamm <- convertX(x$dotdia, "mm", valueOnly = TRUE)
4054
xpos <- xmm
41-
ypos <- ymm + dotdiamm * (x$stackposition * x$stackratio + (1 - x$stackratio) / 2)
55+
ypos <- ymm + dotdiamm * (x$stackposition * x$stackratio + stackoffset)
4256
}
4357

4458
circleGrob(
Lines changed: 74 additions & 0 deletions
Loading

tests/testthat/test-geom-dotplot.R

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,16 @@ test_that("geom_dotplot draws correctly", {
226226
ggplot(dat2, aes(0, x)) + geom_dotplot(binwidth = .4, binaxis = "y", stackdir = "center")
227227
))
228228
})
229+
230+
test_that("stackratio != 1 works", {
231+
df <- data.frame(x = c(rep(1, 3), rep(2, 2)))
232+
233+
expect_doppelganger("stackratio = 1.5",
234+
ggplot(df) +
235+
geom_hline(yintercept = 0) +
236+
geom_dotplot(aes(x), binwidth = 0.5, stackdir = "down", stackratio = 1.5, fill = NA) +
237+
geom_dotplot(aes(x + 3), binwidth = 0.5, stackdir = "up", stackratio = 1.5, fill = NA) +
238+
geom_dotplot(aes(x + 6), binwidth = 0.5, stackdir = "center", stackratio = 1.5, fill = NA) +
239+
geom_dotplot(aes(x + 9), binwidth = 0.5, stackdir = "centerwhole", stackratio = 1.5, fill = NA)
240+
)
241+
})

0 commit comments

Comments
 (0)