Reputation: 338
I'm new to d3.js and am following the example at http://code.tutsplus.com/tutorials/building-a-multi-line-chart-using-d3js-part-2--cms-22973 to build a nested time series for my application.
However, I run into this error despite the data looking like the nested data in the example
Error: Invalid value for <path> attribute d="MNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaN"
My code is here, jsfiddle is http://jsfiddle.net/absail/h9hds98f/
nested_data = [{"key":"False","values":[{"date":"09/04/2015","val":0},{"date":"09/05/2015","val":222},{"date":"09/06/2015","val":168},{"date":"09/07/2015","val":203},{"date":"09/08/2015","val":219},{"date":"09/09/2015","val":237},{"date":"09/10/2015","val":241},{"date":"09/11/2015","val":397},{"date":"09/12/2015","val":158},{"date":"09/13/2015","val":154},{"date":"09/14/2015","val":193},{"date":"09/15/2015","val":202},{"date":"09/16/2015","val":218},{"date":"09/17/2015","val":466},{"date":"09/18/2015","val":439},{"date":"09/19/2015","val":278},{"date":"09/20/2015","val":271},{"date":"09/21/2015","val":475},{"date":"09/22/2015","val":494},{"date":"09/23/2015","val":498},{"date":"09/24/2015","val":503},{"date":"09/25/2015","val":437},{"date":"09/26/2015","val":286},{"date":"09/27/2015","val":280},{"date":"09/28/2015","val":496},{"date":"09/29/2015","val":514}]},{"key":"True","values":[{"date":"09/05/2015","val":3170},{"date":"09/11/2015","val":8643},{"date":"09/04/2015","val":0},{"date":"09/08/2015","val":6146},{"date":"09/12/2015","val":2414},{"date":"09/14/2015","val":5711},{"date":"09/19/2015","val":4118},{"date":"09/26/2015","val":3990},{"date":"09/06/2015","val":2565},{"date":"09/09/2015","val":6426},{"date":"09/13/2015","val":2514},{"date":"09/15/2015","val":5690},{"date":"09/16/2015","val":6222},{"date":"09/17/2015","val":10858},{"date":"09/18/2015","val":9718},{"date":"09/20/2015","val":4006},{"date":"09/21/2015","val":11135},{"date":"09/23/2015","val":11264},{"date":"09/25/2015","val":8831},{"date":"09/27/2015","val":3984},{"date":"09/28/2015","val":11554},{"date":"09/07/2015","val":5562},{"date":"09/10/2015","val":6505},{"date":"09/22/2015","val":11405},{"date":"09/24/2015","val":11411},{"date":"09/29/2015","val":12086}]}];
var parseDate = d3.time.format("%m/%d/%Y").parse;
var color = d3.scale.category10();
var vis = d3.select("#visualisation"),
WIDTH = 1000,
HEIGHT = 500,
MARGINS = {
top: 50,
right: 20,
bottom: 50,
left: 50
},
lSpace = WIDTH/nested_data.length;
xScale = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(nested_data, function(d) {
return d.date;
}), d3.max(data, function(d) {
return d.date;
})]),
yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(nested_data, function(d) {
return d.val;
}), d3.max(data, function(d) {
return d.val;
})]),
xAxis = d3.svg.axis()
.scale(xScale),
yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
vis.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
.call(xAxis);
vis.append("svg:g")
.attr("class", "y axis")
.attr("transform", "translate(" + (MARGINS.left) + ",0)")
.call(yAxis);
var lineGen = d3.svg.line()
.x(function(d) {
return xScale(d.date);
})
.y(function(d) {
return yScale(d.val);
});
// .interpolate("basis");
// Loop through each symbol / key
nested_data.forEach(function(d, i) {
vis.append('svg:path')
.attr('d', lineGen(d.values))
.attr('stroke', function(d,j) {
return "hsl(" + Math.random() * 360 + ",100%,50%)";
})
.attr('stroke-width', 2)
.attr('id', 'line_'+d.key)
.attr('fill', 'none');
vis.append("text")
.attr("x", (lSpace/2)+i*lSpace)
.attr("y", HEIGHT)
.style("fill", "black")
.attr("class","legend")
.on('click',function(){
var active = d.active ? false : true;
var opacity = active ? 0 : 1;
d3.select("#line_" + d.key).style("opacity", opacity);
d.active = active;
})
.text(d.key);
});
I realize this is a common error faced by others, but it seems each time the solution was different. Some suggestions included parsing the date, but that didn't seem to solve the issue for me. Any help would be greatly appreciated, as I've been staring at this for hours. Thanks!
Upvotes: 0
Views: 70
Reputation: 14591
The problem is, you have set the wrong values as the domain
of xScale
and and yScale
.
To set the correct domain values, you should either change the data structure as shown below and use the data array to set the domain.
var data = [{"date":"09/04/2015","val":0,"status":false},
{"date":"09/05/2015","val":222,"status":false},
{"date":"09/06/2015","val":168,"status":false},
{"date":"09/07/2015","val":203,"status":false},
{"date":"09/08/2015","val":219,"status":false},
{"date":"09/09/2015","val":237,"status":false},
{"date":"09/10/2015","val":241,"status":false},
{"date":"09/11/2015","val":397,"status":false},
{"date":"09/12/2015","val":158,"status":false},
{"date":"09/13/2015","val":154,"status":false},
{"date":"09/14/2015","val":193,"status":false},
{"date":"09/15/2015","val":202,"status":false},
{"date":"09/16/2015","val":218,"status":false},
{"date":"09/17/2015","val":466,"status":false},
{"date":"09/18/2015","val":439,"status":false},
{"date":"09/19/2015","val":278,"status":false},
{"date":"09/20/2015","val":271,"status":false},
{"date":"09/21/2015","val":475,"status":false},
{"date":"09/22/2015","val":494,"status":false},
{"date":"09/23/2015","val":498,"status":false},
{"date":"09/24/2015","val":503,"status":false},
{"date":"09/25/2015","val":437,"status":false},
{"date":"09/26/2015","val":286,"status":false},
{"date":"09/27/2015","val":280,"status":false},
{"date":"09/28/2015","val":496,"status":false},
{"date":"09/29/2015","val":514,"status":false},
{"date":"09/05/2015","val":3170,"status":true},
{"date":"09/11/2015","val":8643,"status":true},
{"date":"09/04/2015","val":0,"status":true},
{"date":"09/08/2015","val":6146,"status":true},
{"date":"09/12/2015","val":2414,"status":true},
{"date":"09/14/2015","val":5711,"status":true},
{"date":"09/19/2015","val":4118,"status":true},
{"date":"09/26/2015","val":3990,"status":true},
{"date":"09/06/2015","val":2565,"status":true},
{"date":"09/09/2015","val":6426,"status":true},
{"date":"09/13/2015","val":2514,"status":true},
{"date":"09/15/2015","val":5690,"status":true},
{"date":"09/16/2015","val":6222,"status":true},
{"date":"09/17/2015","val":10858,"status":true},
{"date":"09/18/2015","val":9718,"status":true},
{"date":"09/20/2015","val":4006,"status":true},
{"date":"09/21/2015","val":11135,"status":true},
{"date":"09/23/2015","val":11264,"status":true},
{"date":"09/25/2015","val":8831,"status":true},
{"date":"09/27/2015","val":3984,"status":true},
{"date":"09/28/2015","val":11554,"status":true},
{"date":"09/07/2015","val":5562,"status":true},
{"date":"09/10/2015","val":6505,"status":true},
{"date":"09/22/2015","val":11405,"status":true},
{"date":"09/24/2015","val":11411,"status":true},
{"date":"09/29/2015","val":12086,"status":true}];
var nested_data = d3.nest()
.key(function(d) {
return d.status;
})
.entries(data);
var xScale = d3.scale.linear()
.range([MARGINS.left, WIDTH - MARGINS.right])
.domain([d3.min(data, function(d) {
return new Date(d.date);
}), d3.max(data, function(d) {
return new Date(d.date);
})]),
yScale = d3.scale.linear()
.range([HEIGHT - MARGINS.top, MARGINS.bottom])
.domain([d3.min(data,function(d) {
return d.val;
}), d3.max(data, function(d) {
return d.val;
})]);
or
Keep the nested_data
array as it is and generate the total list of date and values to set find the domain values.
var allValues = nested_data.map(function(d){ return d.values }).reduce(function(a,b){ return d3.merge([a,b]); });
var xScale = d3.scale.linear()
.range([MARGINS.left, WIDTH - MARGINS.right])
.domain([d3.min(allValues, function(d) {
return new Date(d.date);
}), d3.max(allValues, function(d) {
return new Date(d.date);
})]),
yScale = d3.scale.linear()
.range([HEIGHT - MARGINS.top, MARGINS.bottom])
.domain([d3.min(allValues,function(d) {
return d.val;
}), d3.max(allValues, function(d) {
return d.val;
})]);
Note: Also use
new Date(d.date);
instead of d.date
Upvotes: 1
Reputation: 32327
Mistake 1:
The way you calculate max and min is wrong:
yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(nested_data, function(d) {
return d.val;
}), d3.max(data, function(d) {
return d.val;
})]),
Here nested_data is an array of object which has values array. So the max min will not work correctly.
Fix:
You need to collect all the values in the array and make a single array like this:
//get the array of all values.
var arrays = nested_data.map(function (k) {
return k.values
});
var collect = [].concat.apply([], arrays);
Mistake 2:
Not handling the date correctly in the code.
xScale = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(nested_data, function(d) {
return d.date;
}), d3.max(data, function(d) {
return d.date;//this is a string d3 does not know its a date
})]),
Fix:
You will need to convert it into date like this
var parseDate = d3.time.format("%m/%d/%Y").parse;
//get the array of all values.
var arrays = nested_data.map(function (k) {
return k.values
});
var collect = [].concat.apply([], arrays);
//converting date
collect.forEach(function(d){d.date1 = parseDate(d.date)});
Then x axis max min function will be like
xScale = d3.time.scale().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(collect, function (d) {
return d.date1;
}), d3.max(collect, function (d) {
return d.date1;
})]),
yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(collect, function (d) {
return d.val;
}), d3.max(collect, function (d) {
return d.val;
})]),
Full working corrected code here
Hope this helps!
Upvotes: 1