-
Notifications
You must be signed in to change notification settings - Fork 287
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
Support ordinal scale inversion. #60
base: main
Are you sure you want to change the base?
Conversation
var n = domain.length; | ||
while (--n >= 0) invIndex.set(range[n], n+1); | ||
} | ||
return domain[invIndex.get(_ + "") - 1]; |
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.
Coercing _
to a string shouldn’t be necessary here since it will be done by map.get. (Sometimes it’s good to force that coercion earlier, as when a value will be referenced multiple times. But _
is only referenced once here, so might as well avoid it.)
The new ordinal.invert feature seems reasonable. I think the only thing I’d change would be to rename the internal variable to I’m less certain about {band,point}.invert, so if you want to merge ordinal.invert right away it’d be helpful to break it out into a separate pull request. Perhaps part of it is that band.invert overloads the meaning of scale.invert slightly, and there are also two overloaded forms of band.invert (one- and two-argument). It makes me think of quantize.invertExtent, which is not called quantize.invert because it returns the extent of values from the domain rather than just a single value. Perhaps band.invertExtent would be a better name, here? (Although normally I think of an extent as being defined just by two values, so maybe that’s not a big improvement.) Also I need to think through whether the upper and lower bounds should be inclusive or exclusive etc. It’s tricky. |
Thanks. I can break this up into 2 PRs as you suggest. For our own purposes, the band/point scale inversion is the more valuable of the features, as it provides a useful mechanism for brushing and linking over ordinal spatial domains. I also thought about possibly naming this method One question for you regarding |
You don’t strictly need a new API to support brushing and linking over ordinal domains. This example should be easily ported to the D3 4.0 API: http://bl.ocks.org/mbostock/4349509 That said I do not mean to suggest that band.invert and point.invert are not useful; I think they likely are. I just need more time to think about their design before I can commit to supporting them indefinitely. |
I've updated this PR to include only |
It occurs to me that this also (inadvertently) exposes point.invert and band.invert because of how band and point scales are implemented… |
Now deletes the |
Thanks. I have two minor remaining considerations:
I find it hard to answer these questions because I don’t have a good motivating use case: it seems like the primary use case is brushing a band or point scale, not an ordinal scale. I think I need to make some examples first. If you have other ideas for how this could be useful, please let me know. |
I raised the array return value issue in a question for you in an earlier comment. If you'd like to provide array return values (in which case perhaps something like
As for use cases, you're absolutely right that band and point scales are the primary motivation for these inversion PRs. I initially included (vanilla) ordinal inversion for API parity / completeness. |
I appreciate you mentioning it earlier; I’m just keeping notes. That seems like a pretty clean and simple implementation of ordinal.invertExtent. What do you think? Is it useful? |
This PR adds methods and test cases for inverting ordinal scales. The methods can be useful for supporting interaction (e.g., selection, brushing) over ordinal encodings.
For base ordinal scales, an inverted index is constructed as needed to perform simple reverse lookups. The method returns undefined if no matching domain value exists. If the scale has duplicate range values, the domain element with lowest index in the domain array is returned.
For spatial (band/point) scales, either a single point or spatial range can be inverted. Binary search of discretized range values is used to determine indices into the domain array. Adjustments are included to respect padding between bands. The return value is an array of domain elements spanned by the input range, or undefined if no valid elements are found.