1

I'm learning D3 and have JSON data. I want to build multiple bars from this JSON data to draw graph like this already built in excel. I can draw one line of Pax_Rev on SVG but I'm not sure how to add other lines from the data. When I do console.log(dataset.length), it shows me 0 which means only one item in dataset which is expected.

enter image description here

<script>
    var dataset = [{"Pax_Rev": 1000, "Crg_Rev": 500, 
                    "Fixed_Costs": 800, "Variable_Costs": 200}];

    var width = 500;
    var height = 1000;
    var barPadding = 1;

    var svg = d3.select("body")
                .append("svg")
                .append("g")
                .attr("width", width)
                .attr("height", height)
                .attr("class", "svg")

               svg3.selectAll("rect")
                    .data(dataset)
                    .enter()
                    .append("rect")
                    .attr("x", 0)
                    .attr("y", function(d){
                    return height - d.Pax_Rev // How to add other items like Crg_Rev etc?
                    })
                    .attr("width", 20)
                    .attr("height", function(d){
                    return d.Pax_Rev
                    });
</script>
1
  • I have been able to find a work around to change .data(dataset) to following: .data(Object.values(dataset[0])) Commented Aug 7, 2017 at 19:40

1 Answer 1

1

As I explained in your previous question, this is the expected behaviour. Since you have just one object in your data array, D3 "enter" selection will create just one element.

If you look at the API, you'll see that selection.data():

Joins the specified array of data with the selected elements[...] The specified data is an array of arbitrary values (e.g., numbers or objects). (emphases mine)

Therefore, we have to convert that huge object in several objects. This is one of several possible approaches:

var dataset = [{
  "Pax_Rev": 1000,
  "Crg_Rev": 500,
  "Fixed_Costs": 800,
  "Variable_Costs": 200
}];

var data = [];

for (var key in dataset[0]) {
  data.push({
    category: key,
    value: dataset[0][key]
  })
}

console.log(data)

Now, we have a data array, with several objects, one for each bar, and we can create our bar chart.

Here is a demo:

var dataset = [{
  "Pax_Rev": 1000,
  "Crg_Rev": 500,
  "Fixed_Costs": 800,
  "Variable_Costs": 200
}];

var data = [];

for (var key in dataset[0]) {
  data.push({
    category: key,
    value: dataset[0][key]
  })
}

var svg = d3.select("svg");
var yScale = d3.scaleLinear()
  .domain([0, d3.max(data, function(d) {
    return d.value
  })])
  .range([120, 10]);
var xScale = d3.scaleBand()
  .domain(data.map(function(d) {
    return d.category
  }))
  .range([40, 280])
  .padding(0.2);

var rects = svg.selectAll(null)
  .data(data)
  .enter()
  .append("rect")
  .attr("fill", "steelblue")
  .attr("x", function(d) {
    return xScale(d.category)
  })
  .attr("width", xScale.bandwidth())
  .attr("y", function(d) {
    return yScale(d.value)
  })
  .attr("height", function(d) {
    return 120 - yScale(d.value)
  });

var yAxis = d3.axisLeft(yScale);
var xAxis = d3.axisBottom(xScale);

svg.append("g").attr("transform", "translate(40,0)").call(yAxis);
svg.append("g").attr("transform", "translate(0,120)").call(xAxis);
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Gerardo, I have kind of figured out now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.