D3.js Donut Chart With Inner Rings using .csv files

时间:2015-11-12 11:09:53

标签: javascript csv d3.js

My question is similar to that asked here : D3.js - Donut charts with multiple rings

In that question, there was the use of nested arrays to draw the inner rings in the posted jsFiddle: http://jsfiddle.net/Qh9X5/154/ referenced as a solution to the problem.

I am trying to implement the donut chart with inner rings but this time using a csv file. This is my current code:

var margin = {top: 20, right: 30, bottom: 30, left: 30},
	width = 500 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom,
    donutWidth = 50;
    //radius = Math.min(width, height) / 2;

var color = d3.scale.category10();	

var pie = d3.layout.pie()
    //.value(function(d){ return d.count;})
    .sort(null);

var arc = d3.svg.arc();
    //.innerRadius(radius - donutWidth)
    //.outerRadius(radius - 50);

var chart1 = d3.select("#chartArea1").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
.append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); 

d3.csv("data/svm-prediction.csv", function(error, data) {
  if (error) throw error;

  var classNames = d3.keys(data[0]).filter(function(key) { return key !== "Class"; });

  data.forEach(function(d) {
      d.predValues = classNames.map(function(name) { return {name: name, value: +d[name]}; });
  });

  var gs = chart1.selectAll("g").data(d3.values(function(d){ return d.predValues; })).enter().append("g");

  var path = gs.selectAll('path')
        .data(function(d){ return pie(d); })
      .enter().append('path')
        .attr('d', function(d, i , j) { return
          arc.innerRadius(10+donutWidth*j).outerRadius(donutWidth*(j+1))(d);
        })
        .attr('fill', function(d, i) { return color(d.data.Class); });

});

I keep running the code, but it doesn't display on the webpage. I am trying to show the counts for the predicted and actual classes, grouped by the class names. Please assist.

This is the format of the csv file:

Class,Actual_Class,Predicted_Class,Accuracy
Class A,495,495,100
Class B,495,492,99
Class C,495,495,100
Class D,495,495,100
Class E,495,495,100

1 个答案:

答案 0 :(得分:1)

与您发布的小提琴类似,我们尝试将我们从csv获得的数据转换为实际值和预测值的数据数组。我确信可能有更好的方法来做到这一点,但一个简单,直接的方法将如下:

var donutData = new Array,
    actualValues = new Array,
    predValues = new Array;

data.forEach(function(d) {
  actualValues.push(d.Actual_Class);
  predValues.push(d.Predicted_Class);
});

donutData.push(actualValues);
donutData.push(predValues);

您不必对类名和所有内容进行过滤。我们创建的donutData对象(2D数组)可以直接用于创建圆环图。 接下来,在创建gs时,您尝试使用绑定数据而不实际绑定任何绑定数据。所以用以下代码替换该行:

var gs = chart1.selectAll("g").data(donutData).enter().append("g");

现在我们已经将数据很好地绑定到g个标签,每个类一个,我们可以继续创建圆环图:

var path = gs.selectAll('path')
    .data(function(d){ return pie(d); })
  .enter().append('path')
    .attr('d', function(d, i , j) { 
      return arc.innerRadius(10+donutWidth*j).outerRadius(donutWidth*(j+1))(d);
    })
    .attr('fill', function(d, i) { return color(i); });

请注意,我使用pie(d)来选择我们构造的相应数组。此外,我只是将i传递给color()以生成不同的颜色。 d3.csv()部分看起来像这样:

d3.csv("data.csv", function(error, data) {
  if (error) console.log("error reading csv");

  var donutData = new Array,
      actualValues = new Array,
      predValues = new Array;    

  data.forEach(function(d) {
      actualValues.push(d.Actual_Class);
      predValues.push(d.Predicted_Class);
  });

  donutData.push(actualValues);
  donutData.push(predValues);

  var gs = chart1.selectAll("g").data(donutData).enter().append("g");

  var path = gs.selectAll('path')
        .data(function(d){ return pie(d); })
      .enter().append('path')
        .attr('d', function(d, i , j) { 
          return arc.innerRadius(10+donutWidth*j).outerRadius(donutWidth*(j+1))(d);
        })
        .attr('fill', function(d, i) { return color(i); });

});

希望这是你真正想要的。