I'm creating a 3-line chart using D3v7 but only 1 is showed. I'm unable to figure out why.
This is my dataset:
Check out my code below: // Setup SVG
var svg = d3.select("body").append("svg")
.attr("width", width + paddingLeft + paddingRight)
.attr("height", height + paddingTop + paddingBottom)
.append("g")
.attr("transform",
"translate(" + paddingLeft + "," + paddingTop + ")");
// Setup scales
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var colourScale = d3.scaleOrdinal(d3.schemeCategory10);
//Line generator
var line = d3.line()
.x(function(d) {return x(d.monthyear);
})
.y(function(d) { return y(d.total); });
// Load data
d3.csv('adidas_west_sales.csv').then(buildLineChart);
var parseTime = d3.timeParse("%Y-%m");
function buildLineChart(data)
{
data.forEach(function(d)
{
d.MonthYear = parseTime(d.MonthYear);
})
var salesMethods = data.columns.slice(1).map(function(method)
{
return { method: method,
values: data.map(function(d) {
return { monthyear: d.MonthYear,
total: parseFloat(d[method])
}
}
)}
});
console.log(salesMethods);
// Setup scales with data
x.domain(d3.extent(data, function(d) {
return d.MonthYear;}));
y.domain([
d3.min(salesMethods, function(b) {
return d3.min(b.values, function(d) {
return d.total;
});
}),
d3.max(salesMethods, function(b) {
return d3.max(b.values, function(d) {
return d.total;
});
})
]);
colourScale.domain(salesMethods.map(function(c) { return c.method}))
// Add Axis
svg.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x)
.ticks(24)
.tickFormat(d3.timeFormat("%b-%Y")))
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-65)");;
svg.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("fill", "#000")
.text("Total Sale, $");
// Add lines
const lineGraph =
svg.selectAll("path")
.data(salesMethods)
.enter()
.append("path")
.attr('stroke', function(d, i) { return colourScale(i)})
.attr('stroke-width', 1.25)
.style("fill", "none")
.attr("d", function(d) { return line(d.values); });
}
salesMethods
returns 3 values: "Online", "Instore", "Outlet" but there is only 1 line showed.
Is there something missing? Any help would be greatly appreciated!
Your data is essentially an array of arrays. When you get to adding your lines you need to have an outer data-bind so that d3 iterates over the outer array:
const lineGraph = svg
.selectAll('.line')
.data(salesMethods)
.enter()
.append('g') //<-- create a `g` for each outer-array
.attr('class', 'line')
.append('path') //<-- then add the path
.attr('stroke', function (d, i) {
return colourScale(i);
})
.attr('stroke-width', 1.25)
.style('fill', 'none')
.attr('d', function (d, i) {
return line(d.values);
});
Running code here.