In my code below I have restructured the following csv file from something like this:
date,type
2017-01,E
2017-01,E
2017-01,E
2017-01,U
To this:
{date: "2017-01", E: 3, U: 1}
Using d3.nest()
with a rollup
method.
The only thing is that I'm mapping out the type values somewhat manually like this:
var lineData = nestData.map(function(d) {
return {date: d.key, E: d.values[0].value, U: d.values[1].value};
});
always expecting the types to be in order. I do this by simply sorting the data by type
and then re-sort by date
again.
What I basically want to know is if there's a better way of achieving this or if there's a step or two that I can omit from the code making it more efficient.
Here's all the code:
var csvData =
`date,type
2017-01,E
2017-01,E
2017-01,E
2017-01,U
2017-01,U
2017-02,E
2017-02,E
2017-02,U
2017-02,U
2017-02,U
2017-03,U
2017-03,U
2017-03,E
2017-03,E
2017-03,E
2017-03,E`;
var durations = 0;
var parseTime = d3.timeParse("%Y-%m");
var margin = {top: 25, right: 25, bottom: 25, left: 25},
width = 420 - margin.left - margin.right,
height = 185 - margin.top - margin.bottom;
var g = 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 x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
z = d3.scaleOrdinal(d3.schemeCategory10);
var xAxis = d3.axisBottom(x)
.tickFormat(d3.timeFormat("%B"))
.ticks(3);
var yAxis = d3.axisLeft(y).ticks(4);
var line = d3.line()
.curve(d3.curveCardinal)
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.lines); });
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")");
g.append("g")
.attr("class", "axis axis--y");
var data = d3.csvParse(csvData, function(d) {
d.date = d.date;
d.type = d.type
return d;
}).sort((a, b) => a.type - b.type)
var nestData = d3.nest()
.key(d => d.date)
.key(d => d.type)
.rollup(leaves => leaves.length)
.entries(data);
console.log("Nested: ", nestData)
var lineData = nestData.map(function(d) {
return {date: d.key, E: d.values[0].value, U: d.values[1].value};
});
lineData.forEach(function(d) {
d.date = parseTime(d.date);
})
lineData.sort((a, b) => a.date - b.date)
console.log("Mapped: ", lineData)
parsed(lineData);
function parsed(dataTest) {
var keys = ["E","U"]
var newData = keys.map(function(id) {
return {
id: id,
values: dataTest.map(function(d) {
return {date: d.date, lines: d[id]};
})
};
});
console.log("Mapped w/key: ", newData)
z.domain(newData.map(function(c) { return c.id; }));
var max = d3.max(dataTest, d => d3.max([d.E, d.U]));
y.domain([0, max]).nice();
x.domain(d3.extent(dataTest, d => d.date));
g.selectAll(".axis.axis--y").transition()
.duration(durations)
.call(yAxis);
g.selectAll(".axis.axis--x").transition()
.duration(durations)
.call(xAxis);
var lineValues = g.selectAll(".lineValues")
.data(newData);
lineValues = lineValues
.enter()
.append("path")
.attr("class", "line lineValues")
.style("stroke", function(d) { return z(d.id); })
.merge(lineValues);
lineValues.transition()
.duration(durations)
.attr("d", function(d) { return line(d.values) })
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
<html>
<head>
<meta charset ="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style type="text/css">
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
</head>
<body>
<div id="chart"></div>
<script>
</script>
</body>
</html>