I'm new to D3 having problems parsing the x-axis for a positive and negative value bar chart, as seen here:http://bl.ocks.org/mbostock/2368837
Instead of showing the actual year, it is repeating '1970' which is when the time code starts counting. I think it might be an error where the year is not being converted to a string, but it doesn't seem to be a simple d3.timescale since bar charts require the ordinal axis.
var data = [
{"date":19990101,"change":123000},
{"date":19990102,"change":409000},
{"date":19990103,"change":108000},
{"date":19990104,"change":373000},
{"date":19990105,"change":213000},
{"date":19990106,"change":263000},
{"date":19990107,"change":293000},
{"date":19990108,"change":191000},
{"date":19990109,"change":203000},
{"date":19990110,"change":403000},
{"date":19990111,"change":291000},
{"date":19990112,"change":300000},
{"date":20000101,"change":233000},
{"date":20000102,"change":130000},
{"date":20000103,"change":471000},
{"date":20000104,"change":287000},
{"date":20000105,"change":225000},
{"date":20000106,"change":-46000},
{"date":20000107,"change":166000},
{"date":20000108,"change":2000},
{"date":20000109,"change":127000},
{"date":20000110,"change":-12000},
{"date":20000111,"change":223000},
{"date":20000112,"change":138000},
{"date":20010101,"change":-32000},
{"date":20010102,"change":69000},
{"date":20010103,"change":-29000},
{"date":20010104,"change":-281000},
{"date":20010105,"change":-41000},
{"date":20010106,"change":-126000},
{"date":20010107,"change":-122000},
{"date":20010108,"change":-156000},
{"date":20010109,"change":-244000},
{"date":20010110,"change":-327000},
{"date":20010111,"change":-296000},
{"date":20010112,"change":-172000},
{"date":20020101,"change":-143000},
{"date":20020102,"change":-135000},
{"date":20020103,"change":-22000},
{"date":20020104,"change":-83000},
{"date":20020105,"change":-6000},
{"date":20020106,"change":52000},
{"date":20020107,"change":-92000},
{"date":20020108,"change":-14000},
{"date":20020109,"change":-58000},
{"date":20020110,"change":124000},
{"date":20020111,"change":7000},
{"date":20020112,"change":-162000},
{"date":20030101,"change":89000},
{"date":20030102,"change":-158000},
{"date":20030103,"change":-215000},
{"date":20030104,"change":-51000},
{"date":20030105,"change":-10000},
{"date":20030106,"change":-3000},
{"date":20030107,"change":20000},
{"date":20030108,"change":-44000},
{"date":20030109,"change":105000},
{"date":20030110,"change":197000},
{"date":20030111,"change":13000},
{"date":20030112,"change":119000},
{"date":20040101,"change":159000},
{"date":20040102,"change":43000},
{"date":20040103,"change":333000},
{"date":20040104,"change":247000},
{"date":20040105,"change":306000},
{"date":20040106,"change":78000},
{"date":20040107,"change":37000},
{"date":20040108,"change":125000},
{"date":20040109,"change":155000},
{"date":20040110,"change":343000},
{"date":20040111,"change":65000},
{"date":20040112,"change":128000},
{"date":20050101,"change":130000},
{"date":20050102,"change":240000},
{"date":20050103,"change":135000},
{"date":20050104,"change":362000},
{"date":20050105,"change":168000},
{"date":20050106,"change":246000},
{"date":20050107,"change":372000},
{"date":20050108,"change":192000},
{"date":20050109,"change":65000},
{"date":20050110,"change":81000},
{"date":20050111,"change":335000},
{"date":20050112,"change":158000},
{"date":20060101,"change":274000},
{"date":20060102,"change":316000},
{"date":20060103,"change":280000},
{"date":20060104,"change":181000},
{"date":20060105,"change":21000},
{"date":20060106,"change":80000},
{"date":20060107,"change":210000},
{"date":20060108,"change":179000},
{"date":20060109,"change":159000},
{"date":20060110,"change":-3000},
{"date":20060111,"change":205000},
{"date":20060112,"change":169000},
{"date":20070101,"change":234000},
{"date":20070102,"change":90000},
{"date":20070103,"change":186000},
{"date":20070104,"change":76000},
{"date":20070105,"change":141000},
{"date":20070106,"change":80000},
{"date":20070107,"change":-35000},
{"date":20070108,"change":-24000},
{"date":20070109,"change":77000},
{"date":20070110,"change":86000},
{"date":20070111,"change":111000},
{"date":20070112,"change":93000},
{"date":20080101,"change":14000},
{"date":20080102,"change":-85000},
{"date":20080103,"change":-79000},
{"date":20080104,"change":-215000},
{"date":20080105,"change":-186000},
{"date":20080106,"change":-169000},
{"date":20080107,"change":-216000},
{"date":20080108,"change":-270000},
{"date":20080109,"change":-459000},
{"date":20080110,"change":-472000},
{"date":20080111,"change":-775000},
{"date":20080112,"change":-705000},
{"date":20090101,"change":-794000},
{"date":20090102,"change":-695000},
{"date":20090103,"change":-830000},
{"date":20090104,"change":-704000},
{"date":20090105,"change":-352000},
{"date":20090106,"change":-472000},
{"date":20090107,"change":-351000},
{"date":20090108,"change":-210000},
{"date":20090109,"change":-233000},
{"date":20090110,"change":-170000},
{"date":20090111,"change":-21000},
{"date":20090112,"change":-220000},
{"date":20100101,"change":-13000},
{"date":20100102,"change":-40000},
{"date":20100103,"change":154000},
{"date":20100104,"change":229000},
{"date":20100105,"change":521000},
{"date":20100106,"change":-130000},
{"date":20100107,"change":-86000},
{"date":20100108,"change":-37000},
{"date":20100109,"change":-43000},
{"date":20100110,"change":228000},
{"date":20100111,"change":144000},
{"date":20100112,"change":95000},
{"date":20110101,"change":69000},
{"date":20110102,"change":196000},
{"date":20110103,"change":205000},
{"date":20110104,"change":304000},
{"date":20110105,"change":115000},
{"date":20110106,"change":209000},
{"date":20110107,"change":78000},
{"date":20110108,"change":132000},
{"date":20110109,"change":225000},
{"date":20110110,"change":166000},
{"date":20110111,"change":174000},
{"date":20110112,"change":230000},
{"date":20120101,"change":311000},
{"date":20120102,"change":271000},
{"date":20120103,"change":205000},
{"date":20120104,"change":112000},
{"date":20120105,"change":125000},
{"date":20120106,"change":87000},
{"date":20120107,"change":153000},
{"date":20120108,"change":165000},
{"date":20120109,"change":138000},
{"date":20120110,"change":160000},
{"date":20120111,"change":247000},
{"date":20120112,"change":219000},
{"date":20130101,"change":148000},
{"date":20130102,"change":332000},
{"date":20130103,"change":142000},
{"date":20130104,"change":199000},
{"date":20130105,"change":195000},
{"date":20130106,"change":195000}
];
var margin = {top: 34, right: 0, bottom: 30, left: 60},
width = 900;
height = 420 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y%d%m").parse;
formatValue = d3.format(",");
formatTime = d3.time.format("%Y");
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], 0.2);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickPadding(10)
.ticks(20)
.orient("top")
.tickFormat(function(d) { return d3.time.format('%Y')(new Date(d)); });
// .tickFormat(d3.time.format("%Y"));
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// });
x.domain(data.map(function(d) {
return +d.date;
}));
y.domain(d3.extent(data, function(d) {
return d.change;
})).nice();
// add grid lines
function make_X_axis() {
return d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(6);
}
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", function(d) { return d.change < 0 ? "bar negative" : "bar positive"; })
.attr("y", function(d) {
if (d.change < 0) {
return y(0);
} else {
return y(d.change);
}
})
.attr("x", function(d) {
return x(d.change);
})
.attr("height", function(d) {
return Math.abs(y(d.change) - y(0));
})
.attr("width", x.rangeBand())
.on("mouseover", function(d) {
//Get this bar's x/y values, then augment for the tooltip
var xPosition = parseFloat(d3.select(this).attr("x")) + x.rangeBand() / 2;
var yPosition = parseFloat(d3.select(this).attr("y")) / 2 + height / 2;
//Update the tooltip position and value
d3.select("#tooltip")
.style("left", xPosition + "px")
.style("top", yPosition + "px")
.style("right", xPosition + "px")
.select("#value")
// .text(formatValue(d.change)) + formatTime(d.date);
.text(formatValue(d.change));
//Show the tooltip
d3.select("#tooltip").classed("hidden", false);
})
.on("mouseout", function() {
//Hide the tooltip
d3.select("#tooltip").classed("hidden", true);
});
// Update the inner dimensions.
var g = svg.select("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Regular x-axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis.orient("bottom").tickValues([1999, 20000101, 20010101, 20020101, 20030101, 20040101, 20050101, 20060101, 20070101, 20080101, 20090101, 20100101, 20110101, 20120101, 20130101]))
.style("text-anchor", "start");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("x", -25)
.attr("y", -25)
.style("text-anchor", "end")
.text("Jobs");
svg.append("g")
.attr("class", "grid")
.call(make_Y_axis()
.tickSize(-width, 0, 0)
.tickFormat(""));
// //Zero axis
svg.append("g")
.attr("transform", "translate(0," + Y0() + ")")
.call(xAxis.tickFormat("").tickSize(1));
// add grid lines
function make_X_axis() {
return d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(6);
}
function make_Y_axis() {
return d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
}
function Y0() {
return y(0);
}
You need to fix your representation of dates. There are several common ways to represent dates in JavaScript:
As a number (e.g., 1375284578036) representing the number of milliseconds since UNIX epoch.
As an arbitrary string (e.g., "2013-07-31"); this is typically parsed with d3.time.format.
As a bonafide Date object (e.g., new Date(2013, 6, 31)).
In general, your strategy should be to get things into Date objects as quickly as possible, because this is the canonical representation in JavaScript. You should only use a number or a string to represent (“serialize”) dates in a data file, such as CSV or JSON. In sum, always represent dates as Date objects in-code, and convert strings or numbers to Date objects on load as necessary.
In your code, you appear to be using a number of the form YYYYMMDD (with the exception of the first tick value of your x-axis, which is YYYY). Because there are no leading zeroes in the years you are using (i.e., they are all four digits), it’s technically possible to represent a date this way and then coerce it to a string before parsing it with d3.time.format—but this is a bad idea. You should use a string to serialize your dates, rather than a number; only use a number for milliseconds since UNIX epoch.
Notice in your x-axis tick format you are saying new Date(d). This is taking one of the domain values (a number of the form YYYYMMDD) and then converting it to a Date object using the Date constructor. But when the Date constructor is passed a single number, it assumes this is milliseconds since epoch, which is why all of your dates are in the 1970s.
If you convert all your dates to Date objects first when the data is loaded, then the domain of your x-scale will be Date objects, and you won’t need to coerce to dates as part of formatting ticks. You can simply use d3.time.format("%Y") as your tick format.