Skip to content
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

DC extents, high side non-inclusive? #568

Closed
mr23 opened this issue Apr 6, 2014 · 8 comments
Closed

DC extents, high side non-inclusive? #568

mr23 opened this issue Apr 6, 2014 · 8 comments
Labels
Milestone

Comments

@mr23
Copy link
Contributor

mr23 commented Apr 6, 2014

Can someone comment on why the high end of ranges is non-inclusive while the low side is inclusive?

I'm seeing on area selections in the scatterplot the highest point(s) are not included. If I change the extent code to use <= instead of < then it functions as expected.

dc.filters.RangedFilter
return value >= this[0] && value < this[1]
dc.filters.RangedTwoDimensionalFilter
_chart.fadeDeselectedArea
and possibly other locations.

I expect this is because it is using the same basic filter code as for Dimensions, which by nature you do not want to double include points at boundaries between/into groups. However, the charting selection needs to be inclusive.

I might get around to fixing this, but not this weekend.

bloer pushed a commit to bloer/dc.js that referenced this issue May 23, 2014
@gordonwoodhull gordonwoodhull added this to the v2.0 milestone Jun 5, 2014
@mr23
Copy link
Contributor Author

mr23 commented Jun 5, 2014

I just ran across this again, in a barChart, a brush up to the xAxisMax would not include the highest valued sample, for the same reason. I'm temporarily working around it with the following code:

In filters.js, at the top:

/**
#### dc.filters.RangedFilter(function(low,high,bInclusiveHigh))
This function accepts a third parameter indicating whether the high endpoint is included
**/
dc.filters.RangedFilter = function(low, high, bInclusiveHigh) {
    var range = Array(low, high, bInclusiveHigh);
    range.isFiltered = function(value) {
        return value >= this[0] && ( ( this[2] && value <= this[1]) || (!this[2] && value < this[1]));
        // or if you prefer                ( ( this[2] ? value <= this[1] : value < this[1]));
    };

    return range;
};

And in coordinate-grid-mixin.js, near/about line 774:

var rangedFilter = dc.filters.RangedFilter(extent[0], extent[1], _chart.xAxisMax() == extent[1]); // now inclusive of xAxisMax

@mr23
Copy link
Contributor Author

mr23 commented Jun 6, 2014

I just happened to run across this in dc.barChart

dc.override(_chart, "xAxisMax", function() {
    var max = this._xAxisMax();
    if('resolution' in _chart.xUnits()) {
        var res = _chart.xUnits().resolution;
        max += res;
    }
    return max;
});

and also found that "dc.units.fp.precision(precision)" has

_f.resolution = precision;

so perhaps another (untested) workaround would be to apply fp precision to the xAxis ( via .xUnits(dc.units.fp.precision(some precision)) ) thereby increasing the axis max by the precision, allowing the last sample point to now be selectable.

I quick search of the web and I see jrideout is using it in http://bl.ocks.org/jrideout/6826603, but in the intended use of precision.

I like my previously posted solution better as it doesn't depend on knowledge of the data to be used. My application is using loaded csv data which can be of any precision.

@gordonwoodhull
Copy link
Contributor

It makes sense to me that the brush would be closed at the top of the interval, while a filter would be open. It's kind of confusing though. If we make the change, we'd have to come up with some consistent way to translate between UI ranges and crossfilter ranges, which are open at the top:

https://github.com/square/crossfilter/wiki/API-Reference#dimension_filterRange

(Of course, we don't actually use crossfilter ranges, but we should, #478)

@gordonwoodhull
Copy link
Contributor

Are you mostly talking about bar charts here? Is the objective to completely include the range of the top bar which is selected?

Also related: #520 brush partial bar.

@mr23
Copy link
Contributor Author

mr23 commented Jun 6, 2014

Sorry I haven't considered all possible cases, my focus so far in this thread are just on the brushed-barChart and the areaSelection-scatterplot cases.

@Stephen9s
Copy link

You can work around this by adding +1 to your range, if possible; I'm here because I ran into this problem as well, but instead of patching, I went with modifying the range outside the bounds of the known data by calculating the range and adding '+1' to the max.

@gordonwoodhull
Copy link
Contributor

gordonwoodhull commented Dec 22, 2016

As noted in #1066, .xAxisPadding("0.001%") will make the last point selectable if you're using .elasticX(true), and this will work with any magnitude. Again, independent padding #1203 would be nice here. #1066 also shows how to turn off clamping, which is another workaround.

Per #478, RangedFilter is usually "optimized out" to use dimension.filterRange instead, and that uses inclusive lower bound, exclusive upper bound. It's a very computer-sciencey way to go about things, but given that crossfilter is more of a UI library than a computational library, it's arguable that it should do what you expect rather than what's nice mathematically.

@gordonwoodhull
Copy link
Contributor

Given this is the way crossfilter works and there are decent workarounds, I'm closing this. Like it or now, crossfilter defines the standard framework and worldview for dc.js.

I think #792 including the rightmost bar, would also fix this, and that's a more glaring problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants