Skip to content

Fix misalignment in geom_dotplot when stackratio != 1 and stackdir != "up" #4734

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

Merged
merged 4 commits into from
Mar 16, 2022

Conversation

mjskay
Copy link
Contributor

@mjskay mjskay commented Feb 12, 2022

This PR fixes #4614.

The problem

For geom_dotplot() / the dotstack grob, the (1 - x$stackratio) / 2 adjustment on these lines...

if (x$stackaxis == "x") {
dotdiamm <- convertY(x$dotdia, "mm", valueOnly = TRUE)
xpos <- xmm + dotdiamm * (x$stackposition * x$stackratio + (1 - x$stackratio) / 2)
ypos <- ymm
} else if (x$stackaxis == "y") {
dotdiamm <- convertX(x$dotdia, "mm", valueOnly = TRUE)
xpos <- xmm
ypos <- ymm + dotdiamm * (x$stackposition * x$stackratio + (1 - x$stackratio) / 2)
}

...is there because otherwise when stackratio != 1 and stackdir = "up", the base of the first dot in a stack will no longer touch the baseline. This is because stackratio will expand (or contract) the dot stack away (or towards) the origin.

However, currently this adjustment only works correctly for stackdir = "up". For example, here is stackdir = "down" (for other examples, see #4614):

ggplot(data.frame(x = c(rep(1, 3), rep(2, 2))), aes(x)) +
  geom_dotplot(binwidth = 0.5, alpha = 0.5, stackdir = "down", stackratio = 1.5) +
  coord_fixed() +
  ylim(-2, 2) +
  xlim(0, 6)

image

Notice how the top dot in each stack does not touch y = 0 as it should.

The solution

The solution is that the (1 - x$stackratio) / 2 adjustment needs to depend on stackdir:

  • For "up", it should remain (1 - x$stackratio) / 2
  • For "down", it should be reversed: -(1 - x$stackratio) / 2
  • For "center" and "centerwhole", it is unnecessary, and should be 0.

This PR implements that change, and includes test cases to ensure the adjustment is correct when stackratio < 1 and when stackratio > 1.

Copy link
Member

@hadley hadley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this 😄. As well addressing the comments, can you please add a bullet to the top of NEWS.md? It should briefly describe the change and end with (@yourname, #issuenumber).

@@ -125,6 +125,34 @@ test_that("geom_dotplot draws correctly", {
ggplot(dat, aes(x)) + geom_dotplot(binwidth = .4, stackdir = "centerwhole") + coord_flip()
)

# Stacking methods with stackratio < 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please make this a separate test? (The existing huge test unfortunately isn't a good pattern to follow). And can you please also create the smallest possible dataset needed to demonstrate the problem?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, done --- I pulled out the four tests for stackratio = 1.5 into a separate test with a single doppelganger on a simplified dataset that should be sensitive to problems with any of the four values of stackdir. Dunno if you would rather those be four separate small doppelgangers or one merged doppelganger as I have done.

expect_doppelganger("stack up, stackratio = 0.5",
ggplot(dat, aes(x)) + geom_dotplot(binwidth = .4, stackdir = "up", stackratio = 0.5)
)
expect_doppelganger("stack down, stackratio = 0.5",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think one test with non-default stack ratio would be adequate. Visual tests are expensive to maintain so we really want to keep them as minimal as possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@mjskay
Copy link
Contributor Author

mjskay commented Mar 16, 2022

Happy to, thanks for the feedback! I've added a NEWS entry and updated the tests based on your comments.

Copy link
Member

@hadley hadley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Visual test is perfect, thanks!

@hadley hadley merged commit 5ce5cf7 into tidyverse:main Mar 16, 2022
schloerke added a commit to schloerke/ggplot2 that referenced this pull request Mar 23, 2022
* master: (320 commits)
  Orientation-aware key glyphs (tidyverse#4757)
  Fix warning in geom_violin with draw_quantiles (tidyverse#4654)
  Fix misalignment in geom_dotplot when stackratio != 1 and stackdir != "up" (tidyverse#4734)
  Replace coord_equal in scale-identity.r (tidyverse#4759)
  Unified message format in `geom_smooth()` (tidyverse#4634)
  Add parentheses to mentions of binned_scale in scale-alpha and scale-viridis documentation (tidyverse#4735)
  Update geom-boxplot.r (tidyverse#4744)
  Remove unneeded backslash from diamonds docs (tidyverse#4711)
  Re-document
  Warn on unsupported geoms in annotate() (tidyverse#4721)
  Re-document
  Add Trump to presidential terms dataset (tidyverse#4702)
  Corrects bins / binwidth override documentation (tidyverse#4720)
  Update infrastructure to new best practices (tidyverse#4748)
  remove stringsAsFactor for the mapped_discrete as.data.frame method (tidyverse#4750)
  Workflow updates (tidyverse#4747)
  Ensure output is numeric even if ifelse clause is NA (tidyverse#4692)
  Add non_missing_aes to geom_tile (tidyverse#4683)
  Pass on binwidth and height to geom (tidyverse#4671)
  Check for range == NULL - happens if no data has been added to plot (tidyverse#4682)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Dots misaligned in geom_dotplot
2 participants