简体   繁体   English

使用CSV文件的D3.js多系列折线图

[英]D3.js multi-series line chart using csv file

I am trying to recreate a multi-line chart like this example: multi-series line chart 我正在尝试重新创建一个多折线图,例如以下示例: 多系列折线图

This is my initial data file: 这是我的初始数据文件:

module_category,component_category,date_repair,actual,predicted
M1,P06,2009/01,39,63
M1,P06,2009/10,3,4
M1,P06,2009/11,4,3
M1,P06,2009/12,4,2
M1,P06,2009/02,29,45
M1,P06,2009/03,29,32
M1,P06,2009/04,10,22
M1,P06,2009/05,13,15
M1,P06,2009/06,9,16
M1,P06,2009/07,7,12
M1,P06,2009/08,5,9
M1,P06,2009/09,4,5
M1,P09,2009/01,7,5
M1,P09,2009/10,3,1
M1,P09,2009/02,2,3
M1,P09,2009/03,6,2
M1,P09,2009/04,4,2
M1,P09,2009/06,1,2
M1,P09,2009/07,3,2

I want to plot the date on the x-axis and the values for "actual" and "predicted" on the y-axis as two separate lines, but with a sum of the values specific to each particular date. 我想在x轴上绘制日期,并在y轴上绘制“实际”和“预测”的值,以两条单独的线绘制,但是每个特定日期的特定值之和。 For example, the total number of "actual" and "predicted" repair values for "January 2009". 例如,“ 2009年1月”的“实际”和“预测”维修值的总数。

After modifying the code from the example I get this: 在修改示例中的代码后,我得到了:

current displayed chart 当前显示的图表

The big red spheres (shown in the picture) are meant to represent repair values higher than a particular threshold, which is in my code. 大红色球体(如图所示)用于表示高于我的代码中特定阈值的修复值。 The final dataset generated before plotting is meant to look like this: 绘制之前生成的最终数据集应如下所示:

date_repair,Actual,Predicted    
01/01/2009,11027,13250
01/02/2009,8862,12592
01/03/2009,12696,12254
01/04/2009,10666,12014
01/05/2009,10732,11776
01/06/2009,11304,16044
01/07/2009,12880,15133
01/08/2009,11582,13481
01/09/2009,9426,8314
01/10/2009,5250,6510
01/11/2009,4075,4941
01/12/2009,2789,3519

I then considered using a nesting function with the keys as the dates but that doesn't display anything on the page. 然后,我考虑将嵌套函数与键一起用作日期,但是该函数不会在页面上显示任何内容。

 function datelineChart(){ var margin = {top: 20, right: 90, bottom: 30, left: 60}, width = 980 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var parseDate = d3.time.format("%Y/%m").parse; var x = d3.time.scale() .range([0, width]); var y = d3.scale.linear() .range([height, 0]); var color = d3.scale.category10(); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(d3.format(".2s")); var line = d3.svg.line() .interpolate("basis") .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.no_repairs); }); var svg = d3.select("#maincontent").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 + ")"); d3.csv("data/Consolidated_result.csv", function(error, data) { if (error) throw error; data = d3.nest() .key(function(d) { return d.date_repair;}).sortKeys(d3.ascending) .rollup(function(values){ var counts = {}, keys = ['actual', 'predicted'] keys.forEach(function(key){ counts[key] = d3.sum(values, function(d){ return d[key]}) }) return counts }) .entries(data); data.forEach(function(d){ d.date = parseDate(d.key); }) var repairs = data.map(function(d) { return { date: d.date, no_repairs: d.values}; }); console.log(repairs) x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([ d3.min(repairs, function(c) { return d3.min(c.no_repairs); }), d3.max(repairs, function(c) { return d3.max(c.no_repairs); }) ]); var module = svg.selectAll(".module") .data(repairs) .enter().append("g") .attr("class", "module"); var path = svg.selectAll(".module").append("path") .attr("class", "line") .attr("d", function(d) { return line(d.no_repairs); }) .style("stroke", function(d) { return color(d.date); }); var totalLength = [path[0][0].getTotalLength(), path[0][1].getTotalLength()]; console.log(totalLength); d3.select(path[0][0]) .attr("stroke-dasharray", totalLength[0] + " " + totalLength[0]) .attr("stroke-dashoffset", totalLength[0]) .transition() // Call Transition Method .duration(10000) // Set Duration timing (ms) .ease("linear") // Set Easing option .attr("stroke-dashoffset", 0)// Set final value of dash-offset for transition .each("end", function(){ labels.transition() .delay(function(d, i){ return i * 1000; }) .style("opacity",1); }); d3.select(path[0][1]) .attr("stroke-dasharray", totalLength[1] + " " + totalLength[1]) .attr("stroke-dashoffset", totalLength[1]) .transition() // Call Transition Method .duration(10000) // Set Duration timing (ms) .ease("linear") // Set Easing option .attr("stroke-dashoffset", 0);// Set final value of dash-offset for transition .each("end", function(){ labels.transition() .delay(function(d, i){ return i * 1000; }) .style("opacity",1); }); var point = module.append("g") .attr("class", "line-point"); point.selectAll('circle') .data(function(d){ return d.values}) .enter().append("circle") .attr("cx", function(d, i) { return x(d.date)}) .attr("cy", function(d, i) { return y(d.value)}) .attr("r", 5) .style("fill", "white") .style("stroke", function(d) { if(d.value < 14000){ return color(this.parentNode.__data__.name); }else{ return d3.select(this).attr("r",15).style("fill","red").style("stroke","red"); } }); var labels = module.append("text") .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; }) .attr("class","label") .attr("transform", function(d) { return "translate(" + x(d.key) + "," + y(d.values) + ")"; }) .attr("x", 3) .attr("dy", ".35em") .style("opacity", 0) .text(function(d) { return d.name; }); 

Also using viewing the value of the "path" in the console shows an empty array. 同样在控制台中使用“ path”的值查看也会显示一个空数组。 Please assist. 请协助。

Just sort your data before plotting the chart. 只需在绘制图表之前对数据进行排序即可。

data.sort(function(a, b) {
  return a.date - b.date
});

 var margin = { top: 20, right: 90, bottom: 30, left: 60 }, width = 980 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var parseDate = d3.time.format("%Y/%m").parse; var x = d3.time.scale() .range([0, width]); var y = d3.scale.linear() .range([height, 0]); var color = d3.scale.category10(); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(d3.format(".2s")); var line = d3.svg.line() .interpolate("basis") .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.no_repairs); }); var svg = d3.select("#maincontent").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 data = [{ "module_category": "M1", "component_category": "P06", "date_repair": "2009/01", "actual": 39, "predicted": 63 }, { "module_category": "M1", "component_category": "P06", "date_repair": "2009/10", "actual": 3, "predicted": 4 }, { "module_category": "M1", "component_category": "P06", "date_repair": "2009/11", "actual": 4, "predicted": 3 }, { "module_category": "M1", "component_category": "P06", "date_repair": "2009/12", "actual": 4, "predicted": 2 }, { "module_category": "M1", "component_category": "P06", "date_repair": "2009/02", "actual": 29, "predicted": 45 }, { "module_category": "M1", "component_category": "P06", "date_repair": "2009/03", "actual": 29, "predicted": 32 }, { "module_category": "M1", "component_category": "P06", "date_repair": "2009/04", "actual": 10, "predicted": 22 }, { "module_category": "M1", "component_category": "P06", "date_repair": "2009/05", "actual": 13, "predicted": 15 }, { "module_category": "M1", "component_category": "P06", "date_repair": "2009/06", "actual": 9, "predicted": 16 }, { "module_category": "M1", "component_category": "P06", "date_repair": "2009/07", "actual": 7, "predicted": 12 }, { "module_category": "M1", "component_category": "P06", "date_repair": "2009/08", "actual": 5, "predicted": 9 }, { "module_category": "M1", "component_category": "P06", "date_repair": "2009/09", "actual": 4, "predicted": 5 }, { "module_category": "M1", "component_category": "P09", "date_repair": "2009/01", "actual": 7, "predicted": 5 }, { "module_category": "M1", "component_category": "P09", "date_repair": "2009/10", "actual": 3, "predicted": 1 }, { "module_category": "M1", "component_category": "P09", "date_repair": "2009/02", "actual": 2, "predicted": 3 }, { "module_category": "M1", "component_category": "P09", "date_repair": "2009/03", "actual": 6, "predicted": 2 }, { "module_category": "M1", "component_category": "P09", "date_repair": "2009/04", "actual": 4, "predicted": 2 }, { "module_category": "M1", "component_category": "P09", "date_repair": "2009/06", "actual": 1, "predicted": 2 }, { "module_category": "M1", "component_category": "P09", "date_repair": "2009/07", "actual": 3, "predicted": 2 }]; color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date_repair" })); data.forEach(function(d) { d.date = parseDate(d.date_repair); }); data.sort(function(a, b) { return a.date - b.date }); console.log(data); var repairs = color.domain().map(function(name) { return { name: name, values: data.map(function(d) { return { date: d.date, no_repairs: +d[name] }; }) }; }); console.log(repairs); x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([ d3.min(repairs, function(c) { return d3.min(c.values, function(v) { return v.no_repairs; }); }), d3.max(repairs, function(c) { return d3.max(c.values, function(v) { return v.no_repairs; }); }) ]); console.log("comment1"); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 0 - margin.left) .attr("x", 0 - (height / 2)) .attr("dy", "1em") .style("text-anchor", "middle") .text("Number of Repairs"); console.log("comment2"); var module = svg.selectAll(".module") .data(repairs) .enter().append("g") .attr("class", "module"); var path = svg.selectAll(".module").append("path") .attr("class", "line") .attr("d", function(d) { return line(d.values); }) .style("stroke", function(d) { return color(d.name); }); console.log("comment3"); var totalLength = [path[0][0].getTotalLength(), path[0][1].getTotalLength()]; console.log(totalLength); d3.select(path[0][0]) .attr("stroke-dasharray", totalLength[0] + " " + totalLength[0]) .attr("stroke-dashoffset", totalLength[0]) .transition() // Call Transition Method .duration(10000) // Set Duration timing (ms) .ease("linear") // Set Easing option .attr("stroke-dashoffset", 0) // Set final value of dash-offset for transition .each("end", function() { labels.transition() .delay(function(d, i) { return i * 1000; }) .style("opacity", 1); }); console.log("comment4"); d3.select(path[0][1]) .attr("stroke-dasharray", totalLength[1] + " " + totalLength[1]) .attr("stroke-dashoffset", totalLength[1]) .transition() // Call Transition Method .duration(10000) // Set Duration timing (ms) .ease("linear") // Set Easing option .attr("stroke-dashoffset", 0) // Set final value of dash-offset for transition .each("end", function() { labels.transition() .delay(function(d, i) { return i * 1000; }) .style("opacity", 1); }); var point = module.append("g") .attr("class", "line-point"); console.log("comment5"); point.selectAll('circle') .data(function(d) { return d.values }) .enter().append("circle") .attr("cx", function(d, i) { return x(d.date) }) .attr("cy", function(d, i) { return y(d.no_repairs) }) .attr("r", 5) .style("fill", "white") .style("stroke", function(d) { if (d.no_repairs < 14000) { return color(this.parentNode.__data__.name); } else { return d3.select(this).attr("r", 15).style("fill", "red").style("stroke", "red"); } }); var labels = module.append("text") .datum(function(d) { return { name: d.name, value: d.values[d.values.length - 1] }; }) .attr("class", "label") .attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.no_repairs) + ")"; }) .attr("x", 3) .attr("dy", ".35em") .style("opacity", 0) .text(function(d) { return d.name; }); 
 path { fill: none; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <div id="maincontent"></div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM