简体   繁体   中英

How to call all values in nested JSON data (d3js)

I have data that is structured as JSON that looks like this (the real data is much larger and each instance has many more variables and attributes):

var json = [
{
    "CLIN": "1",
    "cost": 257,
},
{
    "CLIN": "1",
    "cost": 846,
},
{
    "CLIN": "2",
    "cost": 162         
},
{
    "CLIN": "2",
    "cost": 984
}]

This is what my JS code looks like:

   <script>
        var margin = {top: 20, right: 160, bottom: 35, left: 30};

        var width = 960 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;

        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 dataByCLIN = d3.nest()
            .key(function(d) {return d.CLIN; })
            .entries(json);

  </script>

This successfully nests the data by the CLIN attribute. However, when I attempt to pass all four variables to create four rectangles for my bargraph, it does not return any values

        var bars = svg.selectAll('rect')
                    .data(dataByCLIN)
                    .enter()
                        .append('rect')
                        .attr('width', function(d) { return d.values.cost; })
                        .attr('height', 10)
                        .attr('y', function(d, i) { return i * 20; });

If I run the code below with various array selections:

console.log(dataByCLIN[0].values[0].cost)

It returns the values I need, but the code:

.attr('width', function(d, i, j) { return d[i].values[j].cost; 

is invalid. The console throws the error

Cannot read property 'values' of undefined

I know how to select the data I need, but not the right formatting to pass that data to the d3 function.

What you can do is use a for/forEach for your data dataByCLIN and create rects inside each loop like this:

var bars = svg.selectAll('.rects');
dataByCLIN.forEach(function(d,i1) {
  bars.data(d.values).enter().append('rect').attr('class', 'rects')
    .attr('width', function(d) {
      return d.cost;
    })
    .attr('height', 10)
    .attr('y', function(d, i) {
      return (i+i1+i1+1) * 20 - 20;
    });
});

Here's a fiddle:

 var json = [{ "CLIN": "1", "cost": 257, }, { "CLIN": "1", "cost": 846, }, { "CLIN": "2", "cost": 162 }, { "CLIN": "2", "cost": 984 } ]; var margin = { top: 20, right: 160, bottom: 35, left: 30 }; var width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; 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 dataByCLIN = d3.nest() .key(function(d) { return d.CLIN; }) .entries(json); var bars = svg.selectAll('.rects'); dataByCLIN.forEach(function(d, i1) { bars.data(d.values).enter().append('rect').attr('class', 'rects') .attr('width', function(d) { return d.cost; }) .attr('height', 10) .attr('y', function(d, i) { return (i + i1 + i1 + 1) * 20 - 20; }); }) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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