cloud
cloud

Reputation: 57

cant figure out d3.js error

var margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;
    
var x = d3.scaleBand()
          .range([0, width])
          .padding(0.1);
var y = d3.scaleLinear()
          .range([height, 0]);
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 + ")");
       
var temp = [ {"Gender":"Male","count":5}, {"Gender":"Female","count":2}];
var data=[]
data.push(temp);

	x.domain(data.map(function(d) { return d.Gender; }));
        y.domain([0, d3.max(data, function(d) { return d.count; })]);
  
    svg.selectAll(".bar")
        .data(data)
      .enter().append("rect")
        .attr("class", "bar")
        .attr("x", function(data) { return x(data.Gender); })
        .attr("width", x.bandwidth())
        .attr("y", function(d) { return y(data.count); })
        .attr("height", function(d) { return height - y(data.count); });


    svg.append("g")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x));


    svg.append("g")
        .call(d3.axisLeft(y));
<style> /* set the CSS */

.bar { fill: steelblue; }

</style>
<!DOCTYPE html>

<body><script src="//d3js.org/d3.v4.min.js"></script></body>

I want a graph to plot male and female count. count in y-axis and gender in x-axis my d3.js index.html

where data_json is the this data [ {"Gender":"Male","count":5}, {"Gender":"Female","count":2}];

im getting graph for only 1 set i.e {"Gender":"Male","count":5} if i set data_json to the same else only axis is displayed.

but not together in same graph. Im new to d3.js and unable to figure out the solution. please help.

Upvotes: 2

Views: 497

Answers (1)

Andrew Reid
Andrew Reid

Reputation: 38151

Your error is stems from this:

var temp = [ {"Gender":"Male","count":5}, {"Gender":"Female","count":2}];
var data=[]
data.push(temp);

The d3 .data method takes an array. Combined with an enter selection, one element can be appended per item in the array. temp is already an array, by pushing it to data you are making an array like the follows:

[[ {"Gender":"Male","count":5}, {"Gender":"Female","count":2}]]

This array has only one item, a sub-array. The sub-array is really what you want though. This is also creates problems when using the scales:

x.domain(data.map(function(d) { return d.Gender; }));

As each datum (and there is only one) comprises of an array, d.Gender will be undefined, d[1] will be defined.

Instead, use your temp array as your dataset without pushing it into a new array. Then modify the y, x, and height values of each rect to access d.count or d.Gender rather than data.Gender or data.count (as data.count is undefined, and also not datum specific, while d.count is the count associated with the datum bound to each rect).

Take a look at the snippet below which makes these changes:

var margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = 500 - margin.left - margin.right,
    height = 200 - margin.top - margin.bottom;
    
var x = d3.scaleBand()
          .range([0, width])
          .padding(0.1);
var y = d3.scaleLinear()
          .range([height, 0]);
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 + ")");
       
var data = [ {"Gender":"Male","count":5}, {"Gender":"Female","count":2}];


	x.domain(data.map(function(d) { return d.Gender; }));
        y.domain([0, d3.max(data, function(d) { return d.count; })]);
  
    svg.selectAll(".bar")
        .data(data)
      .enter().append("rect")
        .attr("class", "bar")
        .attr("x", function(data) { return x(data.Gender); })
        .attr("width", x.bandwidth())
        .attr("y", function(d) { return y(d.count); })
        .attr("height", function(d) { return height - y(d.count); });


    svg.append("g")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x));


    svg.append("g")
        .call(d3.axisLeft(y));
<style> /* set the CSS */

.bar { fill: steelblue; }

</style>
<!DOCTYPE html>

<body><script src="//d3js.org/d3.v4.min.js"></script></body>

Upvotes: 2

Related Questions