Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
Added density reducer to bin/group/hexbin #2047
base: main
Are you sure you want to change the base?
Added density reducer to bin/group/hexbin #2047
Changes from 1 commit
07d5824
b44d609
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also need to check whether value is null (like in reduceProportion), and if that is not the case, use a weighted formula.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think when binning on both
x, y
it can also make sense to normalise to have total area 1, see example notebook where thefill
is the density which is compared to a Gaussian distribution. Without ensuring this normalisation, the density goes to zero with the bin size. For this reason I think it makes more sense to doThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you share the example?
If we want this to be consistent, then we should also normalize by hexagon area (binWidth**2) when doing hexbin?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, it should be public now.
Regarding hexbin: Probably that would be consistent, although the right thing to divide by would be the area of the bin in the x-y-variable scale. However,
binWidth
is in pixel scale, right?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing it consistently for hexbin would require to somehow expose the x,y-radii of the hexagonal cells. Basically, this would amount to changing
hbin
in src/transforms/hexbin.js to (addition highlighted with //NEW)and calling it with
hbin(data, I, X, Y, binWidth, scales.x, scales.y)
.Then the correct normalisation in
reduceDensity
would beaccording to the area of a (hexagon)[https://en.wikipedia.org/wiki/Hexagon]
However, this adds some computational overhead by computing this for each hexagonal cell even when the values
rx,ry
are not needed. For linear scales rx, ry is the same for every cell but I am not sure whether the scale functions somehow expose the fact that they are linear if this is the caseThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for researching this. Note that in fact we can't guarantee anything about the x and y scales (they might not be invertible, and they might even not exist, for example when we use a projection).
This makes me think that the normalization by x2-x1 that we do here does in fact not guarantee that the scaling is correct—it will only work if x is linear (or non-existent, because identity is linear). That's the main use case we wanted to solve, but it doesn't generalize: if your histogram's base is against a log scale, the results will be inconsistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I think the issue is that this density reduction makes sense before the scales are applied, but probably not afterwards. As far as I can see this is different between
bin
andhexbin
.What I mean is that for
bin
the density reducer as a concept also makes sense e.g. for logarithmic scales, see an example here https://observablehq.com/d/0ef7cf5eae234601 (sorry for the dots, I don't know how to produce bars in log scale). Here the reducer is applied before the scaling. The scale just influences the final appearance of the plot. Hence the reducer does not guarantee that the area under the curve is 1 after the scaling, but before the scaling. But I would argue that this is the desired behaviour because the goal is to compare the binned density with some real normalised density, irrespective of the plot scale.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would argue the opposite :) If my data warrants using a log scale, it's because the thing that I am interested in analyzing is the log of the value. Scaling is not meant to make things pretty, but to connect to a deeper “truth” about the data.
This is what we do with the linear regression mark: if you use log scales, you get a linear model of the log of the values, which is equivalent to a log regression (or log-log regression if both scales are logarithmic).
To a certain extent, this is also what we do with hexbins: these hexagons are on the scaled values, and do not represent anything meaningful in data space (unless you use similar scales, for example with an aspectRatio of 1).
Linear binning is very different, as it operates in data space: the x/y bins are "rectangles", not squares. And if you want homogenous rectangles you need to manually adapt the bins so that they are equally-spaced (e.g. 1,2,4,8,16,32,64…), this is not provided by the defaults.
And, once you do that, the division by the extent of each bin should end up with the correct result? Here's what it would look like:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that the log scale is used to reveals some truth about the data like exponential scaling.
What I meant to argue is that the reducer I am suggesting, i.e. "density of values normalised to have total area 1" should be normalised such that the area measured before the scaling and not after the scaling is equal to 1.
In my notebook I now have the same chart in three coordinate systems. Here all three charts use the "density" reducer as implemented in by pull request, i.e. with
proportion /= extent.x2 - extent.x1
which is before applying the log-scale. Note that the areas look differently big, in the first plot yellow has a bigger area than blue, while in the second plot it is the other way round. However, in the space of real coordinates all areas have exactly the same size of 1, and this is what I would like the ensure.In the applications I have in mind I plot some histogram of values (in various scalings), and compare it to the PDF of some probability measure (like exponential, Gaussian, Weibull). For this to make sense it is important that the "area under the curve" measured in the "real" coordinate system (not e.g. the log-coordinate system) is equal to 1. This is for instance also how it is done in matplotlib with
plt.hist(Y, bins=100, density=True, log=True)
.I understand that this becomes a bit strange for
hexbin
becausehexbin
does the binning with the scaled values other thanbin
which (by default) does the binning on the raw values (allowing for setting custom thresholds which can be chosen to match the scale). In order for a density reducer to make sense for hexbin there would have to be a canonical way of determining the extent of each bin in the real coordinate space.Large diffs are not rendered by default.