I'm trying to use d3.ticks. According to the documentation, I should be able to restrict the number of ticks displayed on the axis.
However, this doesn't seem to restrict the number of ticks at all:
xAxis = d3.svg.axis().scale(xScale).orient("bottom").ticks(2)
Is it because my scale is ordinal?
JSFiddle here: http://jsfiddle.net/samselikoff/9tfD2/1/
axis.ticks only works when the underlying scale implements a ticks function, which ordinal scales do not. By default, the axis ticks for an ordinal scale are comprised of the scale's domain, but you can override this by supplying explicit tick values with axis.tickValues.
The documentation also says (in the part for scales)
The specified count is only a hint; the scale may return more or fewer values depending on the input domain.
This is what's happening here -- for the ordinal scale, all the values are taken.
You can however override this by providing explicit tick values, e.g.
d3.svg.axis().scale(xScale).orient("bottom").tickValues(["12am", "8pm"])
Related
I've been working with Mike Bostock's stacked bar chart (here: https://bl.ocks.org/mbostock/4679202).
I've successfully made a number of modifications, but what I'm stuck on is trying to add a y axis with ticks and properly scaled values.
I thought it would simply be done by using this:
var yAxisRight = d3.svg.axis().scale(y2) //define ticks
.orient("right").ticks(5);
However, that results in the values for only ONE set of the stack being used for the entire Y axis. This results in an incorrect scale. The values for the range of all stacks COMBINED needs to be used to determine the range of values I believe.
Is there an easy way to do this that I'm missing? To sum the range of all the columns.
If not, how would I write a function to set the range based on the values in all 4 columns?
Here is a working JSfiddle of what I have now (which is incorrect):
https://jsfiddle.net/1jhm7ths/
If I understood correctly what you tried to achieve, you need to compute your range based on your stacked data and not the original ones. I updated your jsFiddle with the following modification on line 92:
y2.domain([0, d3.max(dataByGroup, function(d) { return d3.sum(d.values, function(v) {return v.value;}); })]); //added
What this does is taking each group, computing the sum of all values, and the taking the max of the sums.
On a side note, I would discourage learning d3 v3 and try to focus on the v4 for longer term support, latest functionalities, modulariy, and a ton of other advantages.
I want to create a dynamic bar chart with no of occurences on Y axis. Therefore, I need to make sure that only integer values are shown and this can be done with proper format:
chart.yAxis().tickFormat(d3.format('f'));
Right now I have only integer numbers but I have for example 1 displayed 3 times:
Is there any option to automatically display it in a nice way (i.e. to minimize number of ticks for charts with shorter range)?
chart.yAxis().tickFormat(d3.format("d"));
will work.
When you append the yAxis, define the ticks the same number as the max value of your y
svg.append("g").call(d3.axisLeft(y).ticks(maxY));
Or in your example that would be
chart.yAxis().ticks(maxY);
Or instead of defining the ticks, you could also define the exact tickValues which you can calculate from your values, this way you have the highest control.
I'm using DC.JS scatterplots to let users select points of interest. If you use elastic axis you cannot select the highest value point. Look at the DC.JS example (https://dc-js.github.io/dc.js/examples/scatter-brushing.html). You cannot select the highest point in the left or right plot.
In several cases, the highest or lowest point(s) is exactly what people need to be able to select because those are the outliers we care about. If you disable elastic axis and make sure you specify a range that is higher than the max value, you can select the point.
Is there another solution besides setting the axis domain based on current min/max and expanding them little bit? This is sometimes ugly when the minimum=0 and now your domain needs to include some small negative number.
--Nico
Always when I face this issue, I increase the y domain by 5% manually.
For instance:
var balanceDomain = d3.scale.linear().domain([0, s.balanceDimension.top(1)[0].balance + (s.balanceDimension.top(1)[0].balance*0.05)]);
s.amountOverallScore
.width(400)
.height(400)
.x(someDomain)
.y(balanceDomain)
...
Maybe this is not the best solution, but always work for me.
Hope it helps (=.
In my application the values were always positive and I used the following to get correct behavior:
// using reductio on the all_grp to get easy access to filtered min,max,avg,etc.
totalTimeMinValue = all_grp.top(1)[0].value.min;
totalTimeMaxValue = all_grp.top(1)[0].value.max;
// now use it to scale the charts we want
detail1_chart.y(d3.scale.linear().domain([totalTimeMinValue-1, totalTimeMaxValue+1]));
detail3_chart.y(d3.scale.linear().domain([totalTimeMinValue-1, totalTimeMaxValue+1]));
This keeps both charts in sink. An additional benefit was that my rather large dots (symbolsize=15) are no longer being clipped.
Thanks Roger.
I'm trying to reduce the number of points in a DC.js line chart to improve performance. The docs lead me to believe xUnits() is the way to do this:
The coordinate grid chart uses the xUnits function to calculate the number of data projections on x axis such as the number of bars for a bar chart or the number of dots for a line chart.
but xUnits does not even seem to be used:
http://jsfiddle.net/m5tguakf/2/
What am I doing wrong?
The number of points is actually determined by crossfilter - dc.js doesn't do any aggregation on its own, so it has no way to add or reduce the number of points.
That documentation may be misleading - it doesn't alter the shape of the data. xUnits is really just needed for dc.js to know the number of elements it is going to draw. It's used for two purposes:
to determine the width of bars or box-plots
to know whether the x scale is ordinal or quantitative
Could dc.js just count the number of points in the crossfilter group? Perhaps.
Anyway, to get back to your original question: if you want to reduce the number of points drawn, aggregate your data differently in your group. Usually this means creating larger bins which either sum or average the data which fall into that interval.
As a simple example, you can combine every other point in your fiddle by binning by even numbers, like so:
var BINSIZE = 2;
// ...
speedSumGroup = runDimension
.group(function(r) { return Math.floor(r/BINSIZE) * BINSIZE; })
// ...
http://jsfiddle.net/gordonwoodhull/djrhodkj/2/
This causes e.g. both Run 6 and Run 7 to fall in the same bin, because they have the same group key. In a real example, you'd probably want to average them, as shown in the annotated stock example.
Can someone point me in the direction of what I should be tweaking to get deterministic color band? For example, if they array of colors contains 6 colors, I would like the values 10-30 to always go to the 5th color band, 50-80 to the 6th, etc.
(in case someone is wondering why I need such an odd thing, right now the value 30 shows up in several different colors, depending on what other values are in the set -- can be pretty confusing for a user over time). I thought of restricting the min and max values in the set to achieve stable colors but that would distort the lables. Also, ideally, I would like to specify the mapping of input data value to color myself
This won't let you do arbitrary assignments of values to colors, but you can set the min and max values cubism uses to assign colors with the extent option:
var context = cubism.context();
var horizon = context.horizon();
horizon.extent([-80,80]);
The extent will then be divided up evenly among the color bands you have set.