d3js: maximum value of legend - d3.js

Code below for legend works fine, but doesn't display the maximum value at the end of the last rect. The maximum value is gonna be 36 always, so I don't mind hard coding it, but don't know how to do it. data is an array of integer values ranging between 0 and 36 and the data array is fed into the eye_data[i].value. I cannot provide the actual data as it is uploaded from a database and a separate file takes care of uploading the values.
//this is just an example of the eye_data format
var eye_data = [
{ locus: "p1", coordinates: {x: "4", y: "1"}, value:"" },
{ locus: "p2", coordinates: {x: "5", y: "1"}, value:"" },
{ locus: "p3", coordinates: {x: "6", y: "1"}, value:"" },
{ locus: "p4", coordinates: {x: "7", y: "1"}, value:"" }];
function heat_map_graph() {
var colorScale = d3.scale.quantile()
.domain([0, buckets - 1, d3.max(data, function (d) { return parseInt(d); })])
.range(colors);
var svg = d3.select("#punchcard").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var heatMap = svg.selectAll("g")
.data(eye_data)
.enter().append("rect")
.attr("x", function(d) { return (parseInt(d.coordinates.x) - 1) * gridSize; })
.attr("y", function(d) { return (parseInt(d.coordinates.y) - 1) * gridSize; })
.attr("cx", 4)
.attr("cy", 4)
.attr("class", "hour bordered")
.attr("width", gridSize)
.attr("height", gridSize)
.style("fill", colors[0])
.style("stroke", "black");
heatMap.transition().duration(1000)
.style("fill", function(d) { return colorScale(d.value); });
heatMap.append("title").text(function(d) { return d.value; });
var legend = svg.selectAll(".legend")
.data([0].concat(colorScale.quantiles()), function(d) { return d; })
.enter().append("g")
.attr("class", "legend");
legend.append("rect")
.attr("x", function(d, i) { return legendElementWidth * i; })
.attr("y", height + 30)
.attr("width", legendElementWidth)
.attr("height", gridSize / 2)
.style("fill", function(d, i) { return colors[i]; });
legend.append("text")
.attr("class", "mono")
.text(function(d) { return Math.round(d); })
.attr("x", function(d, i) { return legendElementWidth * i; })
.attr("y", height + 30 + gridSize);
}
How can the maximum value be displayed at the end of the last legend rect ??
Any help much appreciated !!

Related

D3 v5 center path line in a bar graph

I am using d3.js v5 to plot a bar graph , Porblem is while creating a bar graph and and appending path along with bars , paths are not making to the center of a bar instead of that it is placed on the start point , is there any way to center the point, Currently the graph showing is like this
But i want the small circles and points to be in the center
sorry for bad image i am just visualizing my concept brown lines are in center and will be connected by path
var margin = {
top: 10,
right: 30,
bottom: 90,
left: 40
},
width = 900 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
this.x_axis = Array(20).fill(0).map((x, i) => (i + 1) * 5);
this.y_axis = [1.1, 2.2, 3.5, 4.9, 5.3, 6.9, 7.3, 8.1, 9.2, 8.2, 1.3, 0.1, 0.1, 0.4, 0.1, 0.4, 0.2, 0.4, 0.1, 0.2];
let data = [];
for (let i = 0; i < this.x_axis.length; i++) {
data.push({
Country: this.x_axis[i],
Value: this.y_axis[i]
})
}
var svg = d3.select("#graph")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Parse the Data
// X axis
var x = d3.scaleBand()
.range([0, width])
.domain(data.map(function(d) {
return d.Country;
}))
.padding(0.3);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
// Add Y axis
var y = d3.scaleLinear()
.domain([0, 20])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
var x2 = d3.scaleBand()
.range([0, width]);
// Bars
svg.selectAll("mybar")
.data(data)
.enter()
.append("rect")
.attr("x", function(d) {
return x(d.Country);
})
.attr("width", x.bandwidth())
.attr("fill", "#69b3a2")
// no bar at the beginning thus:
.attr("height", function(d) {
return height - y(0);
}) // always equal to 0
.attr("y", function(d) {
return y(0);
})
// Animation
svg.selectAll("rect")
.transition()
.duration(800)
.attr("y", function(d) {
return y(d.Value);
})
.attr("height", function(d) {
return height - y(d.Value);
})
.delay(function(d, i) {
console.log(i);
return (i * 100)
})
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("d", d3.line()
.x(function(d) {
return x(d.Country)
})
.y(function(d) {
return y(d.Value)
}))
svg.selectAll("myCircles")
.data(data)
.enter()
.append("circle")
.attr("fill", "red")
.attr("stroke", "none")
.attr("cx", function(d) {
return x(d.Country)
})
.attr("cy", function(d) {
return y(d.Value)
})
.attr("r", 3)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="graph"></div>
Since you're using a scaleBand, the axis automatically returns not the center, but the top left of the rectangle, by offsetting by about x.bandwidth() / 2. One workaround for this would be to use return x(d.Country) + x.bandwidth() / 2 to find the center of the bars.
var margin = {
top: 10,
right: 30,
bottom: 90,
left: 40
},
width = 900 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
this.x_axis = Array(20).fill(0).map((x, i) => (i + 1) * 5);
this.y_axis = [1.1, 2.2, 3.5, 4.9, 5.3, 6.9, 7.3, 8.1, 9.2, 8.2, 1.3, 0.1, 0.1, 0.4, 0.1, 0.4, 0.2, 0.4, 0.1, 0.2];
let data = [];
for (let i = 0; i < this.x_axis.length; i++) {
data.push({
Country: this.x_axis[i],
Value: this.y_axis[i]
})
}
var svg = d3.select("#graph")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Parse the Data
// X axis
var x = d3.scaleBand()
.range([0, width])
.domain(data.map(function(d) {
return d.Country;
}))
.padding(0.3);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
// Add Y axis
var y = d3.scaleLinear()
.domain([0, 20])
.range([height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
var x2 = d3.scaleBand()
.range([0, width]);
// Bars
svg.selectAll("mybar")
.data(data)
.enter()
.append("rect")
.attr("x", function(d) {
return x(d.Country);
})
.attr("width", x.bandwidth())
.attr("fill", "#69b3a2")
// no bar at the beginning thus:
.attr("height", function(d) {
return height - y(0);
}) // always equal to 0
.attr("y", function(d) {
return y(0);
})
// Animation
svg.selectAll("rect")
.transition()
.duration(800)
.attr("y", function(d) {
return y(d.Value);
})
.attr("height", function(d) {
return height - y(d.Value);
})
.delay(function(d, i) {
console.log(i);
return (i * 100)
})
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("d", d3.line()
.x(function(d) {
return x(d.Country) + x.bandwidth() / 2;
})
.y(function(d) {
return y(d.Value)
}))
svg.selectAll("myCircles")
.data(data)
.enter()
.append("circle")
.attr("fill", "red")
.attr("stroke", "none")
.attr("cx", function(d) {
return x(d.Country) + x.bandwidth() / 2
})
.attr("cy", function(d) {
return y(d.Value)
})
.attr("r", 3)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="graph"></div>

place nodes generated from a force to a radial scatter plot

I have a force layout that generates some node positions for a given node-link diagram. My task is to place these nodes and links to a radial scatter plot. The nodes should be placed in such a way that their distance from the center node can be visible. For this reason, I calculate the euclidean distance of the nodes from the center and find maximum value from the calculated distance. Then scaled the radius of the radial plot within 0 to maximum distance value. But when I tried This example, the node-link diagram did not place upon the scatter plot. My question is how can I place the node co-ordinates to the plot such that the distance of the nodes from the center node can be seen by the circle line of the scatter plot.
Here is a portion of my input data
{
"nodes": [
{
"id": "A0",
"group": 0,
"degree": 19,
"name": "x"
},
{
"id": "P0",
"group": 0,
"degree": 3,
"name": "y"
},
{
"id": "P1",
"group": 0,
"degree": 3,
"name": "z"
},
{
"id": "P2",
"group": 0,
"degree": 1,
"name": "w"
}
],
"links": [
{
"source": "P0",
"target": "A0"
},
{
"source": "P1",
"target": "A0"
},
{
"source": "P2",
"target": "A0"
}
]
}
Here is a portion of my code.
var width = 1200,
height = 800,
radius = Math.min(width, height) / 2 - 30;
//console.log(");
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var rd_at = 3,
rd_pp = 2.5;
var author_cord = [];author_cord.push({x:width / 2,y:height / 2});
var given_person = 'x';
d3.json("json_file.json", function(graph) {
var simulation = d3.forceSimulation(graph.nodes)
.force("charge", d3.forceManyBody().strength(-500))
.force("center", d3.forceCenter(width / 2, height / 2))//ATTRACT NODES TO CENTER(width / 2, height / 2)
.force("x", d3.forceX(width / 2).strength(1))//X ALLIGN
.force("y", d3.forceY(height / 2).strength(1))//Y ALLIGN
.force("link", d3.forceLink(graph.links).id(function(d) {return d.id; ).distance(40).strength(1))
.stop();
var loading = svg.append("text")
.attr("dy", "0.35em")
.attr("text-anchor", "middle")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.text("Simulating. One moment please…");
d3.timeout(function() {
loading.remove();
for (var i = 0, n = Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay())); i < n; ++i) {
simulation.tick();
}
var all_dist = [];
graph.nodes.forEach(function(d){
var d_x = d.x - author_cord[0].x;
var d_y = d.y - author_cord[0].y;
var dist = Math.sqrt(d_x*d_x + d_y+d_y);
all_dist.push(dt);
});
var max_dist = d3.max(all_dist, function(d) {
return d;
});
var r = d3.scaleLinear()
.domain([0,12])
.range([0, max_dist]);
var line = d3.lineRadial()
.radius(function(d) {
return r(d[1]);
});
var gr = svg.append("g")
.attr("class", "r axis")
.selectAll("g")
.data(r.ticks(10).slice(1))
.enter().append("g");
gr.append("circle")
.attr("r", r);
var links = svg.append("g")
.attr("stroke", "grey")
.attr("stroke-width", 1)
.selectAll("line")
.data(graph.links)
.enter().append("line")
.style("opacity", function(d) { return d.target.name == given_author? 0 : 1; } )
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
var n = svg.append("g")
.selectAll("circle")
.data(graph.nodes)
.enter().append("circle")
.attr("r", function(d) {return d.group == 0 ? rd_at : rd_pp;})
.attr("fill", function(d) { return color(d.group); })
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("stroke", "#000")//.attr("stroke", function(d) {return d.group == 0 ? "red": "blue";})
.attr("stroke-width", function(d) {return d.group == 0 ? 1.5 : 1;});
});
});
Here is my output so far. . Here, in the picture green nodes are group 0 node and orange nodes are group 1. Here, center node is the ego node that should be place in the inner most center position of the radial plot
Your svg selection actually corresponds to a group already translated by half width and height:
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
Therefore, you can either change the "center", "x" and "y" in the simulation or, alternatively, you can just remove that group from the svg selection and translating the circles' groups instead:
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var gr = svg.append("g")
.attr("class", "r axis")
.selectAll("g")
.data(r.ticks(10).slice(1))
.enter()
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

d3js animated horizontal chart improvements

I am creating a horizontal animated d3 chart. How do you reverse the x axis and position the bars in a more dynamic way.
Are the bars the correct width or is the xaxis scale correct? Using d3 version 4
//horizontal work in progress
http://jsfiddle.net/ueg3bjf7/
//vertical chart code this is based from
http://jsfiddle.net/myf1zhar/
$(document).ready(function() {
var $this = $(".barchart");
var w = $this.data("width");
var h = $this.data("height");
var data = $this.data("data");
var data = [{
"label": "Apples",
"value": 100
},
{
"label": "Pears",
"value": 120
},
{
"label": "Bananas",
"value": 20
}
];
var configurations = $this.data("configurations");
function colores_google(n) {
var colores_g = ["#f7b363", "#448875", "#2b2d39", "#c12f39", "#f8dd2f", "#1b91dc"];
return colores_g[n % colores_g.length];
}
//asess the margin bottom for the chart based on the max char label
var charLabelCount = [];
data.map(function(d) {
var labelStr = d.label.toString();
charLabelCount.push(labelStr.length);
})
var maxChars = charLabelCount.reduce(function(a, b) {
return Math.max(a, b);
});
var bottomMarg = 60;
if (maxChars > 15) {
bottomMarg = 170;
}
//bottom margin calculation
var margin = {
top: 15,
right: 20,
bottom: bottomMarg,
left: 40
},
width = w - margin.left - margin.right,
height = h - margin.top - margin.bottom;
var x = d3.scaleBand()
.range([0, width]);
var y = d3.scaleLinear()
.range([height, 0]);
var yAxis = d3.axisBottom(y);
var xAxis = d3.axisLeft(x);
var svg = d3.select($this[0])
.append("svg")
.attr("width", w)
.attr("height", h)
.attr("viewBox", "0 0 " + w + " " + h)
.attr("preserveAspectRatio", "xMidYMid meet")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("class", "barchartg");
function sortBy(array, key) {
var sorted = array.sort(function(a, b) {
return parseFloat(b[key]) - parseFloat(a[key]);
});
return sorted;
}
var sortedMax = 45;
if (configurations) {
if (configurations[0]["maxValue"]) {
sortedMax = configurations[0]["maxValue"] + 5;
}
} else {
sortedMax = sortBy(data, "value")[0]["value"] + 5;
}
x.domain(data.map(function(d) {
return d.label;
}));
y.domain([0, sortedMax]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0,25)")
.call(xAxis);
svg.selectAll(".x.axis text")
.attr("transform", "rotate(-60) translate(-5,-5)")
.style("text-anchor", "end");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("");
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("fill", function(d, i) {
return colores_google(i);
})
.attr("x", function(d) {
return 0;
})
.attr("width", function(d) {
return d.value;
})
.attr("y", function(d, i) {
return 45 + (i * 90);
})
.attr("height", function(d) {
return 50;
});
d3.selectAll("rect").transition()
.duration(500)
.delay(function(d, i) {
return 500 * i;
})
.attr("width", function(d) {
return 0;
})
setTimeout(function() {
d3.selectAll("rect").transition()
.duration(500)
.delay(function(d, i) {
return 600 * (3 - i);
})
.attr("width", function(d) {
return d.value;
})
}, 2000);
});
I will try to answer your questions.
How do you reverse the x axis
You have to change the domain of the axis
y.domain([sortedMax, 0]);
position the bars
You have to translate the axis to the width of your graph
svg.append("g").attr("transform", "translate(0, 300)").attr("class", "y axis")
Are the bars the correct width or is the xaxis scale correct?
You have to use a multiplier to calculate the width of each bar, using the max width of your graph and your max value. I have added the 25 pixels of the translate of the x axis
var mult = (w + 25) / sortedMax;
...
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("fill", function(d, i) {
return colores_google(i);
})
.attr("x", function(d) {
return 0;
})
.attr("width", function(d) {
return d.value * mult;
})
.attr("y", function(d, i) {
return 45 + (i * 90);
})
.attr("height", function(d) {
return 50;
});
...
setTimeout(function() {
d3.selectAll("rect").transition()
.duration(500)
.delay(function(d, i) {
return 600 * (3 - i);
})
.attr("width", function(d) {
return d.value * mult;
})
}, 2000);
You can see the result in this fiddle http://jsfiddle.net/jfLgawue/65/

meteor d3 import data

I'm having difficulties in importing data from MongoDB into the D3 heatmap function. An example can be found here: http://bl.ocks.org/tjdecke/5558084
The data looks like this:
[Object { _id="DoaB3wnW7CCzxqzug", weekday=1, hour=1, value=12}, Object { _id="RnwxHbRPGdWHBaAYu", weekday=1, hour=2, value=4}]
My code looks like this:
Template.weeklyUsageHeatmap.rendered = function() {
var margin = { top: 20, right: 0, bottom: 100, left: 20 },
width = 720 - margin.left - margin.right,
height = 340 - margin.top - margin.bottom,
gridSize = Math.floor(width / 24),
legendElementWidth = gridSize*2,
buckets = 9,
colors = ["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"]
days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
times = ["1a", "2a", "3a", "4a", "5a", "6a", "7a", "8a", "9a", "10a", "11a", "12a", "1p", "2p", "3p", "4p", "5p", "6p", "7p", "8p", "9p", "10p", "11p", "12p"];
var data = WeeklyUsage.find().fetch();
d3.json(data,
function(d) {
return {
day: +d.weekday,
hour: +d.hour,
value: +d.value
};
},
function(error, data) {
var colorScale = d3.scale.quantile()
.domain([0, buckets - 1, d3.max(data, function (d) { return d.value; })])
.range(colors);
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var dayLabels = svg.selectAll(".dayLabel")
.data(days)
.enter().append("text")
.text(function (d) { return d; })
.attr("x", 0)
.attr("y", function (d, i) { return i * gridSize; })
.style("text-anchor", "end")
.attr("transform", "translate(-6," + gridSize / 1.5 + ")")
.attr("class", function (d, i) { return ((i >= 0 && i <= 4) ? "dayLabel mono axis axis-workweek" : "dayLabel mono axis"); });
var timeLabels = svg.selectAll(".timeLabel")
.data(times)
.enter().append("text")
.text(function(d) { return d; })
.attr("x", function(d, i) { return i * gridSize; })
.attr("y", 0)
.style("text-anchor", "middle")
.attr("transform", "translate(" + gridSize / 2 + ", -6)")
.attr("class", function(d, i) { return ((i >= 7 && i <= 16) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis"); });
var heatMap = svg.selectAll(".hour")
.data(data)
.enter().append("rect")
.attr("x", function(d) { return (d.hour - 1) * gridSize; })
.attr("y", function(d) { return (d.weekday - 1) * gridSize; })
.attr("rx", 4)
.attr("ry", 4)
.attr("class", "hour bordered")
.attr("width", gridSize)
.attr("height", gridSize)
.style("fill", colors[0]);
heatMap.transition().duration(1000)
.style("fill", function(d) { return colorScale(d.value); });
heatMap.append("title").text(function(d) { return d.value; });
var legend = svg.selectAll(".legend")
.data([0].concat(colorScale.quantiles()), function(d) { return d; })
.enter().append("g")
.attr("class", "legend");
legend.append("rect")
.attr("x", function(d, i) { return legendElementWidth * i; })
.attr("y", height)
.attr("width", legendElementWidth)
.attr("height", gridSize / 2)
.style("fill", function(d, i) { return colors[i]; });
legend.append("text")
.attr("class", "mono")
.text(function(d) { return "≥ " + Math.round(d); })
.attr("x", function(d, i) { return legendElementWidth * i; })
.attr("y", height + gridSize);
});
};
The error I got was: d is NULL.

D3.js stacked Barchart Error

I Need your help... why is this Chart not running.. Error in Console (d3.v2.js Zeile 2396):
TypeError: string.substring is not a function
var n = d3_time_numberRe.exec(string.substring(i, i + 2));
Could anybody help me please?
<script type="text/javascript">
var w = 960,
h = 500,
p = [20, 50, 30, 20],
x = d3.scale.ordinal().rangeRoundBands([0, w - p[1] - p[3]]),
y = d3.scale.linear().range([0, h - p[0] - p[2]]),
z = d3.scale.ordinal().range(["lightpink", "darkgray", "lightblue"]),
parse = d3.time.format("%m/%Y").parse,
format = d3.time.format("%b");
var data = [
[
new Date('1991-01-18T00:00:00'),
52.380001068115234,
28.56999969482422,
10.0
],
[
new Date('1994-11-17T00:00:00'),
57.88999938964844,
21.049999237060547,
10.0
]
];
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + p[3] + "," + (h - p[2]) + ")");
// Transpose the data into layers by cause.
var causes = d3.layout.stack()([data[1], data[2], data[3]].map(function(cause) {
return data.map(function(d) {
return {x: parse(d[0]), y: +d[cause]};
});
}));
// Compute the x-domain (by date) and y-domain (by top).
x.domain(causes[0].map(function(d) { return d.x; }));
y.domain([0, d3.max(causes[causes.length - 1], function(d) { return d.y0 + d.y; })]);
// Add a group for each cause.
var cause = svg.selectAll("g.cause")
.data(causes)
.enter().append("svg:g")
.attr("class", "cause")
.style("fill", function(d, i) { return z(i); })
.style("stroke", function(d, i) { return d3.rgb(z(i)).darker(); });
// Add a rect for each date.
var rect = cause.selectAll("rect")
.data(Object)
.enter().append("svg:rect")
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return -y(d.y0) - y(d.y); })
.attr("height", function(d) { return y(d.y); })
.attr("width", x.rangeBand());
// Add a label per date.
var label = svg.selectAll("text")
.data(x.domain())
.enter().append("svg:text")
.attr("x", function(d) { return x(d) + x.rangeBand() / 2; })
.attr("y", 6)
.attr("text-anchor", "middle")
.attr("dy", ".71em")
.text(format);
// Add y-axis rules.
var rule = svg.selectAll("g.rule")
.data(y.ticks(5))
.enter().append("svg:g")
.attr("class", "rule")
.attr("transform", function(d) { return "translate(0," + -y(d) + ")"; });
rule.append("svg:line")
.attr("x2", w - p[1] - p[3])
.style("stroke", function(d) { return d ? "#fff" : "#000"; })
.style("stroke-opacity", function(d) { return d ? .7 : null; });
rule.append("svg:text")
.attr("x", w - p[1] - p[3] + 6)
.attr("dy", ".35em")
.text(d3.format(",d"));
</script>
The problem is here:
var causes = d3.layout.stack()([data[1], data[2], data[3]].map(function(cause) {
return data.map(function(d) {
return {x: parse(d[0]), y: +d[cause]};
});
}));
d[0] is already a date object - new Date('1991-01-18T00:00:00') - and parse is expecting a string.
Instead, pass d[0] directly:
return {x: d[0], y: +d[cause]};
Sidenote: check out the debugging tools for chrome. Most of the error messages you get working with d3 will not give very useful messages (like "TypeError: string.substring is not a function") and being able to look through the stack is extremely helpful.

Resources