-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Stack mixin charts' y-domain is always [0, n] when elasticY(true) #667
Comments
It definitely should be series or stacks (or something else) but not both. I don't think either is very well thought out, but stacks are debugged better. Note that bar series are sort of a better starting point for grouped bars than stacks (maybe), and that scatter series do exist, although you could argue that it's just coloring based on another variable. Ironically, there is something conceptually missing about multidimensional data in general. This is all kind of road-to-3.0 stuff, but just defining what multidimensional input looks like, in a consistent way (I mean, with accessors rather than just array-of-array gunk), would help a lot. |
I may be wrong, but it seems to me the elasticY property in the above example is consistent with how elasticY (or elasticX in a rowchart) works elsewhere in dc.js, e.g. elasticY in a bar chart draws the scale [0,n] where n is the maximum and changes depending on filtering, same for elasticX in a row chart. |
Interesting point @lbk3918. When I created the issue, I was under the impression Although, [0, n] doesn't always look bad, the problem can be exacerbated when the yScale has low cardinality but really high values (such as my first chart). The lines become flat and blend together. Off topic, that zoom switching sounds pretty cool. |
Yes I can see how elasticX & elasticY seem to work differently - I work mostly with ordinal x-axes (although these are often Month Names or Week Numbers) so I hadn't got that same perspective. I prefer using ordinals because;
The Zoom scale switching was fun to implement, a classic case where a customer wants to focus on the differences but the account manager wants to put the dramatic peaks & troughs into perspective as being between 99-100% & unnoticeable at full scale - so the chart draws (0,100%) initially but can be zoomed in (min, 100%) or out by clicking on an icon by the chart heading. The hardest part was finding the exact correct syntax to set the scale based on extent of the group - most of the dc.js examples seem to use fixed scales rather than data-driven. |
I'm not sure why people associate this problem with the composite charts rather than all line i.e. stack mixin charts. Retitling. It's the classic debate of "should my chart start at zero?" infamous from the classic "how to lie with statistics" book, and I don't think there is one answer that fits for all purposes. |
To generalize the workaround, create a function: function nonzero_min(chart) {
dc.override(chart, 'yAxisMin', function () {
var min = d3.min(chart.data(), function (layer) {
return d3.min(layer.values, function (p) {
return p.y + p.y0;
});
});
return dc.utils.subtract(min, chart.yAxisPadding());
});
return chart;
} Apply this function to a single chart; add it to the |
Earlier discussion, with a preRender/preRedraw - based workaround: #216. |
Thanks Gordon, but I can't find how to apply it to my example: |
In your example: .compose([
nonzero_min(dc.lineChart(chart2)
.dimension(timeDimension)
.colors('red')
.group(enabledA, "enabledA")
// .dashStyle([2,2])
.interpolate('step-after')
.renderArea(false)
.brushOn(false)
.renderDataPoints(true)
.clipPadding(10)),
nonzero_min(dc.lineChart(chart2)
.dimension(timeDimension)
// .colors('red')
.group(enabledC, "enabledC")
// .dashStyle([2,2])
.interpolate('step-after')
.renderArea(false)
.brushOn(false)
.renderDataPoints(true)
.clipPadding(10)),
nonzero_min(dc.lineChart(chart2)
.dimension(timeDimension)
.colors('orange')
.group(enabledB, "enabledB")
// .dashStyle([5,5])
.interpolate('step-after')
.renderArea(false)
.brushOn(false)
.renderDataPoints(true)
.clipPadding(10)) fork of your fiddle: http://jsfiddle.net/gordonwoodhull/7anae5c5/1/ |
partly to illustrate interaction between #667 and alignYAxes
partly to illustrate interaction between #667 and alignYAxes
partly to illustrate interaction between #667 and alignYAxes
How would you modify this so y axis minimum is not exactly minimum of data, but slightly lower so that below 5% of y axis bottom is empty (no y data points), also similarly I want to get a buffer on y axis top so largest points dont touch the top of the y axis |
Hi @erdult. Did you try setting the yAxisPadding which both this and |
Problem
The series chart (which is a composite mixin) draws all stack mixin children (typically line charts) incorrectly when
elasticY
is set to true. I would expect the highest value to be at the top of the chart and the lowest value to be at the bottom, flush with the axis.Here is a screen of the issue:
Because the series chart (composite mixin) will add multiple child charts, the stack mixin is effectively only rendering n number of single group stacks (where the data point has value
{y: value, y0: 0}
. The issue arises when accumulating the y-axis min, in the child'syAxisMin
function ofstack-mixin.js
:Workaround
A workaround is changing the series-chart's
_chartFunction
to properly return the min value for the group, using thechart
method:Thoughts
The more I think about it, the less I like the fact that series is a chart type... It really only applies to line charts. It would be better if the stackMixin handled these cases, such as:
seriesAccessor
functionThe list of bugs around stack & series has been growing for a while, so they definitely deserve some attention and it would be nice to provide an all in one true stack/series/group mixin.
The text was updated successfully, but these errors were encountered: