Search code examples
d3.jsdata-visualizationpie-chart

Cannot read property 'length' of undefined in a pie chart


I am new to d3.js, and while making a pie chart, I am getting the following error:

'd3.v4.js:13909 Uncaught TypeError: Cannot read property 'length' of 
undefined'

My data is of the following format:

  var company = [

 {  
    "company_code": 1,  
    "company_name": "Walmart",
    "health_safety": 3.6,
    "wages": 5,
    "recommended": 4  
  },
  { 
    "company_code": 2,
    "company_name": "HEB",
    "health_safety": 3,
    "wages": 2,
    "recommended": 1
  },
  ]

The code of the following is as follows:

var width = 400;
var height = 400;


//sampling out the data which doesn't have the min_company_code -- for now -- for initial screen



var path = d3.arc()
             .outerRadius(width / 2 - 10)
             .innerRadius(width / 4); 


d3.select('svg')
    .attr('width', width)
    .attr('height', height)
  .append('g')
    .attr('transform', 'translate(' + width / 2 + ', ' + height / 2 + ')')
    .classed('chart', true);

var company_codeData = company.filter(d => d.company_code === 1);
var health = company_codeData[0]['health_safety'];
var parameters = [health, 5 - health];


var arcs = d3.pie()
            .value(parameters);

var path = d3.arc()
             .outerRadius(width / 2 - 10)
             .innerRadius(width / 4);

d3.select('.chart')
      .selectAll('.arc')
      .data(arcs)  // This is the line that gives me the error!!
      .enter()
      .append('path')
        .classed('arc', true)
        .attr('fill', function(d, i){
          return data[i].color;
        })
        .attr('stroke', 'black')
        .attr('d', path);

Is the function being called before the data is loaded? If yes, how do I fix the error? I read that I need to load the data in a callback, but I can't figure out how How do I fix this? Thanks in advance!


Solution

  • Whatever you're trying to do (which I have no idea, since you have a data array with several objects that you're filtering, extracting one value and using it to create a 2-element array), this is incorrect:

    var arcs = d3.pie()
        .value(parameters);
    

    You shoudn't pass the actual data to the value method of the pie generator. You must pass the data to the pie generator itself. In your case:

    var arcs = d3.pie()(parameters);
    

    Also, there is no data or color in your snippet, I changed it to:

    .attr('fill', function(d, i) {
        return i ? "blue" : "green";
    })
    

    Which returns blue or green instead.

    Here is your code with those changes:

    var company = [{
      "company_code": 1,
      "company_name": "Walmart",
      "health_safety": 3.6,
      "wages": 5,
      "recommended": 4
    }, {
      "company_code": 2,
      "company_name": "HEB",
      "health_safety": 3,
      "wages": 2,
      "recommended": 1
    }];
    
    var width = 400;
    var height = 400;
    
    var path = d3.arc()
      .outerRadius(width / 2 - 10)
      .innerRadius(width / 4);
    
    
    d3.select('svg')
      .attr('width', width)
      .attr('height', height)
      .append('g')
      .attr('transform', 'translate(' + width / 2 + ', ' + height / 2 + ')')
      .classed('chart', true);
    
    var company_codeData = company.filter(d => d.company_code === 1);
    var health = company_codeData[0]['health_safety'];
    var parameters = [health, 5 - health];
    
    
    var arcs = d3.pie()(parameters);
    
    var path = d3.arc()
      .outerRadius(width / 2 - 10)
      .innerRadius(width / 4);
    
    d3.select('.chart')
      .selectAll('.arc')
      .data(arcs) // This is the line that gives me the error!!
      .enter()
      .append('path')
      .classed('arc', true)
      .attr('fill', function(d, i) {
        return i ? "blue" : "green";
      })
      .attr('stroke', 'black')
      .attr('d', path);
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <svg></svg>