Wrong display of csv input to nvd3 chart (related to timeformatting)
-
21-12-2019 - |
Question
I have an issue where I try to display average values over a single day; Hours, minutes (%H:%M), but the chart does not properly interpret the data and switches times around, 23:30 comes after 00:00, creating a messy display.
I think the issue is related to how time formatting, but am not sure how. Can anyone identify what is wrong? Any tips are appreciated!
Code
<script>
d3.csv("17_predicted_hourly_holiday.csv", function(error, data) {
data.sort(function(a, b) {
return a.length - b.length;
});
var exampleData = Object.keys(data[0]).filter(function(k) {
return k != 'length'
})
.map(function(k) {
return {
'key': k,
'values': data.map(function(d) {
return [
d3.time.format('%Y-%m-%d' + '%H:%M').parse("2000-01-01" + d.length),
//d3.time.format('%Y-%b-%d' + '%H:%M:%S').parse("2000-01-01" + d.length + ':00')
+d[k]
]
})
}
});
//alert(JSON.stringify(exampleData));
console.log(exampleData);
//console.log(data);
var colors = d3.scale.category20();
keyColor = function(d, i) {
return colors(d.key)
};
var chart;
nv.addGraph(function() {
chart = nv.models.stackedAreaChart()
.x(function(d) {
return d[0]
})
.y(function(d) {
return d[1]
})
.color(keyColor)
.clipEdge(true);
chart.xAxis
.tickFormat(function(d) {
return d3.time.format('%H:%M')(new Date(d));
});
chart.yAxis
.tickFormat(d3.format(',.2f'));
d3.select('#chart')
.datum(exampleData)
.transition().duration(500).call(chart);
nv.utils.windowResize(chart.update);
chart.dispatch.on('stateChange', function(e) {
nv.log('New State:', JSON.stringify(e));
});
return chart;
});
// end read csv
});
Plunker
http://plnkr.co/edit/GYI8oq?p=info
Image of issue: http://i.imgur.com/li1Vee2.png
Solution
The problem is that in your sorting function you're assuming that length
is a number, which it is not. In your case, you don't even need to sort though as the data comes in sorted. Working example here.
Alternatively, you can use a sort function that works with the times:
data.sort(function(a, b) {
return d3.time.format('%Y-%m-%d' + '%H:%M').parse("2000-01-01" + a.length) - d3.time.format('%Y-%m-%d' + '%H:%M').parse("2000-01-01" + b.length);
});
Complete demo here.
On a general note, don't use length
as an attribute name -- it clashes with the .length
that gives you the length of an array in Javascript and will cause problems sooner or later.