Strange spacing of dates on x-axis (D3) - d3.js

I am trying to create a simple column chart using an array of data points of the form[datetime,value], for example [1422345600000,146]. I would like to plot these with the date on the x-axis with labeled ticks every few days. I almost managed to accomplish this, but the first couple of ticks are spaced oddly close together.
You can see it here: http://jsfiddle.net/9r4fqbnm/2/
I tried
var xAxis = d3.svg.axis()
.scale(x)
.orient('bottom')
.ticks(d3.time.days,7)
.tickFormat(d3.time.format("%m/%d/%Y"))
and the ticks after the first two are indeed spaced by 7 days.
I didn't find this issue online--am I missing something obvious?
Thanks

Your problem is your data array. I was too lazy to dig into each value and see which one is the culprit, but basically by converting it into a human readable format and making sure the values are valid - fixes the problem:
function getDate(y, m, d) {
return new Date(y, m, d);
}
var data = [
[getDate(2015, 1, 27), 146], [getDate(2015, 1, 28), 132], ..., [getDate(2015, 2, 24), 67], [getDate(2015, 2, 25), 46]
];
var startDate = data[0][0];
var endDate = data[data.length - 1][0];
...
http://jsfiddle.net/2L3fy90j/1/

Related

set yAxis ticks D3js

I am having time series chart in D3js in that I am setting up yScale like.
setYScale() {
this.yScale = d3
.scaleBand()
.range([this.gHeight, 0])
.domain(this.yData) //this is array [0,1,2,3,4,5....23]
.padding(0.06);
},
This sets tick for me in left side, from 0 to 23 (24hrs), what I would like to achieve is that instead of having it sequential order from 0,1,2,3,4...tick I would like to have 0,2,4,6,8 (even numbers), and rest should work be as it is just ticks I would like to have it as even number. Can anyone help me on this.
Your code is just the scale, assuming you have an axis called axis, try:
axis.tickFormat(function(d) { return (+d)%2 ? '' : d })

DimpleJS. Y axis values in percentages

I am plotting Vertical Grouped Bar Chart from a csv file which contains Discount, Rating and Clicked. The data is csv is like 55,2,1 and 40,5,0 etc. Here the first value(55,40) are the discounts, (2,5) rating and 1 and 0 correspond to clicked and not clicked respectively. On plotting the chart with following code.
var svg2 = dimple.newSvg("#discountContainer", 590, 400);
d3.csv("/svm1000.csv", function (data) {
var myChart2 = new dimple.chart(svg2, data);
myChart2.setBounds(60, 30, 510, 330)
myChart2.addCategoryAxis("x", ["rating", "action"]);
var y = myChart2.addMeasureAxis("y", "discount");
//y.tickFormat = "%";
myChart2.addSeries("action", dimple.plot.bar);
myChart2.addLegend(65, 10, 510, 20, "right");
myChart2.draw();
});
The problem is I want to represent y axis in percentage in multiple of 10, like 0%, 10%, 20% .. 100%. Right now the y axis values are like 0,2k,4k,6k...20k. So how to represent y axis in percentage.
I see this question is old, so this answer may not help you, but for others facing similar requirements this might be helpful.
dimple.js provide method to have percentage series
myChart2.addPctAxis("y", "discount");
but remember you can't create both Value and Percentage in same axis, you might need to have dual axis graph
var x = myChart2.addCategoryAxis("x", ["rating", "action"]);
var y1 = myChart2.addPctAxis("y", "discount");
var y2 = myChart2.addMeasureAxis("y", "amount"); // the field with value ranges 1000...
also you don't able to use grouped bar chart; for axis 1 use bar chart and for axis 2 use line or vice versa like
myChart2.addSeries("action", dimple.plot.bar, [x, y1]);
myChart2.addSeries("action", dimple.plot.line, [x, y2]);

Display different values on axis than those found by the scale function in D3

I have a d3 graph that uses a linear scale for its x axis. It looks something like this:
...
y |
|
+-------------------------------------------
0.0 0.5 1.0 1.5 2.0 2.5 3.0
Time in weeks
Beneath this axis I want to display rows of data aligned to the x axis. Like this:
23 23 22 19
Using this data:
var nums = [23, 23, 22, 19];
var times = [0, 0.5, 1.5, 3];
times are where the nums should fall on the Time in weeks x axis. So the first index of nums falls under 0.0, the second under 0.5, and so on.
The scale function looks something like this:
var x = d3.scale.linear().domain([0,3]).range([0, 600]);
So x(0.5) returns the correct range value for displaying a tick on the new axis. But what I want to display is the corresponding value from the nums array. That is, display the value of nums[times.indexOf(0.5)].
Is there a way to override scale() as used by d3.svg.axis() so that it displays nums values instead of times values while still using times as the input domain?
Edit
Here is a demo
Edit 2
I figured it out thanks to ne8il's answer. The answer was not complete, but it formed the basis for this code:
var x1Axis = d3.svg.axis()
.scale(x1)
.ticks(nums)
.tickValues(times)
.tickFormat(function(x){return nums[times.indexOf(x)];})
Working example
I believe in this case you can do
d3.svg.axis().ticks(times).tickValues(nums);
It will pass each 'time' into your scale function to map it to an x coordinate, and use the corresponding indexed value in 'nums' to output text.
Source is here

Minor tweaks for histogram generated using d3

Following is the stripped down version is what I'm using to generate histograms using d3 and a bit of jQuery.http://bl.ocks.org/4611158
While most of it might seem right, I'm still confused regarding
Why there is no '14' in the x-axis as should have been for the given input in the above example? Instead 13 gets the ordinate of what should have been 14's
In my trials d3.layout.histogram() assigned negative(and hence non-plot table) widths when I try altering the output range of scale to some non-zero value. why is it so? what is the possible workaround?
My main motive to use ordinal scale was to make ticks centrally aligned below the bars, unlike what Mike used in his demo for histograms. I've also made the number of bins equal to the number of ticks in d3.layout.histogram() for the very same purpose. I'm sure there might be a better way around to code what I'm looking for
Also any ideas how to add a 'graph' of indicator lines like its been done in nvd3 visualization (light gray in background )that will make it more pleasing?
There is no 14 and there are two 8s on the x-axis. This is because the bins function will diligently divide the range = 14 - 1 = 13 into 14 intervals as per the API reference:
The bins may be specified as a number, in which case the range of values will be split
uniformly into the given number of bins. Or, bins may be an array of threshold values,
defining the bins; the specified array must contain the rightmost (upper) value, thus
specifying n + 1 values for n bins. ...
Before solving this issue, I am guessing that the second problem you are facing is that if the rangeDefault has negative values, then some values are not plotted. To fix that problem, being unaware of the exact need of it, I will start by removing the following:
rangeDefault[0] = 0; //All histograms start from 0 <-- REMOVED
Then to fix the first problem, use the second form of arguments for binsas shown here:
var bins = [];
for(var ii = settings.range[0], jj = 0; ii <= settings.range[1] + 1; ii++, jj++)
bins[jj] = ii;
var data = d3.layout.histogram()
.bins(bins)(settings.data);
I hope this addresses the primary queries.
Adding the light grey indicator lines is fairly easy, as shown here. The changes were:
vis.css
.y.axis line.tick { opacity: .3; }
vis.js
Moving the axis before the chart in the DOM because of how SVG is laid out affects its z-index:
var gEnter = svg.enter().append("svg").append("g");
gEnter.append("g").attr("class", "x axis");
gEnter.append("g").attr("class","y axis");
gEnter.append("g").attr("class", "bars");
And finally making the major tickSize on the y-axis -(width - margin.right - margin.left):
yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickSubdivide(true)
.tickPadding(5)
.ticks(10)
.tickSize(-(width - margin.right - margin.left), 2, 8);

How do I make a custom axis formatter for hours & minutes in d3.js?

I've got a dataset I'm graphing with d3.js. The x axis represents time (in minutes). I'd like to display this axis in an hh:mm format, and I can't find a way to do this cleanly within d3.
My axis code looks like:
svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(d3.svg.axis()
.scale(x)
.orient('bottom'));
Which generates labels in minutes that looks like [100, 115, 130, 140], etc.
My current solution is to select the text elements after they've been generated, and override them with a function:
svg.selectAll('.x.axis text')
.text(function(d) {
d = d.toFixed();
var hours = Math.floor(d / 60);
var minutes = pad((d % 60), 2);
return hours + ":" + minutes;
});
This outputs axis ticks like [1:40, 1:55, 2:10], etc.
But this feels janky and avoids the use of d3.format. Is there a better way to make these labels?
If you have absolute time, you probably want to convert your x data to JavaScript Date objects rather than simple numbers, and then you want to use d3.time.scale and d3.time.format. An example of "hh:mm" format for an axis would be:
d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.time.format("%H:%M"));
And actually, you may not need to specify a tick format at all; depending on the domain of your scale and the number of ticks, the default time scale format might be sufficient for your needs. Alternatively, if you want complete control, you can also specify the tick intervals to the scale. For example, for ticks every fifteen minutes, you might say:
d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(d3.time.minutes, 15)
.tickFormat(d3.time.format("%H:%M"));
If you have relative time, i.e. durations, (and hence have numbers representing minutes rather than absolute dates), you can format these as dates by picking an arbitrary epoch and converting on-the-fly. That way you can leave the data itself as numbers. For example:
var formatTime = d3.time.format("%H:%M"),
formatMinutes = function(d) { return formatTime(new Date(2012, 0, 1, 0, d)); };
Since only the minutes and hours will be displayed, it doesn't matter what epoch you pick. Here’s an example using this technique to format a distribution of durations:
http://bl.ocks.org/3048166

Resources