Reputation: 1187
I don't have a MWE for this, as it mostly deals with the preprocessing of data prior to writing D3 code.
I have a .csv
file which is essentially structured as follows:
category,value,date
cat1,200000,2016-08-07
cat2,500000,2016-08-07
cat3,600000,2016-08-07
cat1,200000,2016-09-07
cat2,500000,2016-09-07
cat3,600000,2016-09-07
and so forth. The task is to draw a line graph for each one of cat1
, cat2
, and cat3
with the x-axis being the date and the y-axis being the value. From every example I've found, the solution appears to be that there must be one date per row:
date,cat1,cat2,cat3
2016-08-07,200000,500000,600000
2016-09-07,200000,500000,600000
which makes sense. However, let's suppose that cat1
, cat2
, and cat3
have required colors that must be associated with them. For example, suppose that the line for cat1
must have color #4472C4
, the line for cat2
must have color #ED7D31
, and the line for cat3
must have color #FFC000
.
What is the best way to structure the data above to not only easily plot the lines, but to associate each line with a specified color?
If a MWE is preferred, please let me know, and I will delete this question until I have a sufficient MWE prepared.
Upvotes: 1
Views: 111
Reputation: 8509
You can define your custom color scale this way:
var color = d3.scaleOrdinal()
.domain(['cat1', 'cat2', 'cat3'])
.range(["#4472C4", "#ED7D31" , "#FFC000"]);
console.log("color('cat1') ==>", color('cat1'));
console.log("color('cat2') ==>", color('cat2'));
console.log("color('cat3') ==>", color('cat3'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
As you can see it returns the appropriate color for the category name that you pass.
Check the primitive demo how it works in action:
var dataAsCsv = `category,value,date
cat1,200000,2016-08-07
cat2,500000,2016-08-07
cat3,600000,2016-08-07
cat1,400000,2016-09-07
cat2,600000,2016-09-07
cat3,200000,2016-09-07`;
var color = d3.scaleOrdinal()
.domain(['cat1', 'cat2', 'cat3'])
.range(["#4472C4", "#ED7D31" , "#FFC000"]);
var data = d3.csvParse(dataAsCsv);
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 300 - margin.left - margin.right,
height = 100 - margin.top - margin.bottom;
var parseTime = d3.timeParse("%Y-%m-%d");
data.forEach(function(d) {
d.date = parseTime(d.date);
d.value = +d.value;
});
var dataByCategory = d3.nest()
.key(function(d) { return d.category; })
.entries(data);
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.value; })]);
var valueline = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.value); });
var svg = d3.select("body").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 + ")");
svg.selectAll('path')
.data(dataByCategory)
.enter()
.append("path")
.attr("class", "line")
.attr("stroke", function(d){
console.log(color(d.key))
return color(d.key);
})
.attr("d", function(d) {
return valueline(d.values);
});
.line {
fill: none;
stroke-width: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
Upvotes: 1
Reputation: 2550
One thing you could try is to class each line by category, then use css to add colour, something like this:
d3.selectAll("path").data(csv)
.enter().append("path")
.attr("class", function(d){return d.category}
Alternatively, you could also add a colour scale which can be seen here.
Upvotes: 1