Skip to content

Implement filled 2d density contours #3864

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 18 commits into from
Mar 12, 2020

Conversation

clauswilke
Copy link
Member

@clauswilke clauswilke commented Mar 7, 2020

The missing feature from 3.3.0, as described in #3846.

This is work in progress. Still to do:

  • Implement geom_density2d_filled() analogously to geom_contour_filled()
  • Usage examples
  • Make nlevel work for geom_density2d_filled().
  • Unit tests
  • News item
  • Fully document computed variables
  • Improve documentation of stat_contour_filled()

@clauswilke

This comment has been minimized.

@clauswilke
Copy link
Member Author

Never mind. Apparently this works only from inside a stat.

library(tidyverse)

data(airquality)
airQ <- filter_all(airquality, ~!is.na(.))

ggplot(airQ, aes(x = Solar.R, y = Temp)) +
  geom_density2d_filled(alpha = 0.7) +
  geom_density2d(size = 0.25, color = "black") +
  geom_point(size = 1)

Created on 2020-03-07 by the reprex package (v0.3.0)

@clauswilke clauswilke mentioned this pull request Mar 8, 2020
@clauswilke clauswilke mentioned this pull request Mar 9, 2020
@clauswilke clauswilke added this to the ggplot2 3.3.1 milestone Mar 9, 2020
@clauswilke
Copy link
Member Author

@thomasp85 How's this?

library(ggplot2)

ggplot(faithfuld, aes(waiting, eruptions, z = density)) + 
  geom_contour_filled() + 
  facet_wrap(~waiting < 70)

set.seed(4393)
dsmall <- diamonds[sample(nrow(diamonds), 1000), ]
d <- ggplot(dsmall, aes(x, y))

d + geom_density_2d_filled() +
  facet_wrap(~cut)

d + geom_density_2d_filled(contour_var = "ndensity") +
  facet_wrap(~cut)

d + geom_density_2d_filled(contour_var = "count") +
  facet_wrap(~cut)

d + geom_density_2d(aes(color = after_stat(level))) + 
  facet_wrap(~cut)

d + geom_density_2d(aes(color = after_stat(level)), contour_var = "ndensity") + 
  facet_wrap(~cut)

d + geom_density_2d(aes(color = after_stat(level)), contour_var = "count") + 
  facet_wrap(~cut)
#> Warning: stat_contour(): Zero contours were generated
#> Warning in min(x): no non-missing arguments to min; returning Inf
#> Warning in max(x): no non-missing arguments to max; returning -Inf

Created on 2020-03-10 by the reprex package (v0.3.0)

@thomasp85
Copy link
Member

This looks good. The compute_layer approach was exactly what I had in mind...

It hurts a little that contour_var cannot be an aesthetic, but there is no way around that if it all has to happen in a stat...

Some part of me really wants to make the contouring happen in the geom so that anything that ends up as a raster hightmap after the stat can be contoured... but then we end up with the issues of colour scaling the output of contouring –– no singular best solution it seems

@clauswilke
Copy link
Member Author

Some part of me really wants to make the contouring happen in the geom so that anything that ends up as a raster hightmap after the stat can be contoured... but then we end up with the issues of colour scaling the output of contouring –– no singular best solution it seems

If the geom could get the height data from the stat and the binning information from the scale then it might work. We could always in the future add such geoms in addition to geom_contour(), as I did in ggisoband (which conceptually does what you want, it just doesn't quite work right in all cases).

@clauswilke clauswilke changed the title WIP: filled 2d density contours Implement filled 2d density contours Mar 11, 2020
@clauswilke clauswilke requested a review from thomasp85 March 12, 2020 00:17
@clauswilke
Copy link
Member Author

clauswilke commented Mar 12, 2020

I think this is ready for review now. Closes #3846.

Copy link
Member

@thomasp85 thomasp85 left a comment

Choose a reason for hiding this comment

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

Is there any difference between stat_bin2d and the new stat_density_2d() with contour = FALSE. To me they seem superficially equivalent (at least in intend)

#' @usage NULL
#' @export
#' @include geom-polygon.r
GeomContourFilled <- ggproto("GeomContourFilled", GeomPolygon)
Copy link
Member

Choose a reason for hiding this comment

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

What is the purpose of this? Do we have any precedence for creating ggproto aliases?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is needed to auto-generate documentation for aesthetics. We probably should do it more consistently across ggplot2. See here:
https://github.com/clauswilke/ggplot2/blob/743bad010638fdccaed4c0cfa0258e0879e1263c/R/geom-density2d.r#L9-L10

Copy link
Member

Choose a reason for hiding this comment

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

Ah... that seems bad, but is not really the fault of this PR

@clauswilke
Copy link
Member Author

The relationship between stat_bin2d() and stat_density_2d() is equivalent to stat_bin() and stat_density(). One creates a histogram, by making regular-sized bins and simply counting how many observations fall into each bin. The other does a kernel-density estimation. Both are useful, and they are distinct.

@thomasp85
Copy link
Member

You are right. I got bin2d confused

Copy link
Member

@thomasp85 thomasp85 left a comment

Choose a reason for hiding this comment

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

LGTM

@clauswilke clauswilke merged commit 781204d into tidyverse:master Mar 12, 2020
@clauswilke clauswilke deleted the issue-3846-stat-density-2d branch March 12, 2020 20:45
sthagen added a commit to sthagen/tidyverse-ggplot2 that referenced this pull request Mar 13, 2020
Implement filled 2d density contours (tidyverse#3864)
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.

2 participants