Fallen lord
Fallen lord

Reputation: 316

Basic D3 - Working with arrays inside objects

I'm pretty new to D3 and I'm stuck right now in a particular subject that I suppose it's very basic. I've been researching the whole day for something that could help me but everything I've found ended up not being exactly what I need, anyway I apologize from now if it has already been asked.

Basically, I've been creating scatterplots using arrays so far, like:

 var dataset = [[100,220],[130,350],[70,60],[100,140],[520,300],[120,280],[390,170]];

And then:

     var chart = d3.select("body")
    .append("svg")
    .attr("width",w)
    .attr("height",h);

    var plot = chart
    .selectAll("circle")
    .data(dataset)
    .enter()
    .append("circle")
    .attr("cx",function(d){return d[0];})
    .attr("cy",function(d){return d[1];})
    .attr("r",function(d,i){return i*4});

If now I want to work with a dataset made of objects instead of arrays it does still work fine with a few adjustments:

var dataset = [
    {x:100,y:220},
    {x:130,y:350},
    {x:70,y:60},
    {x:100,y:140},
    {x:520,y:300},
    {x:120,y:280},
    {x:390,y:170}
    ];

The updated code:

    var chart = d3.select("body")
    .append("svg")
    .attr("width",w)
    .attr("height",h);

    var plot = chart
    .selectAll("circle")
    .data(dataset)
    .enter()
    .append("circle")
    .attr("cx",function(d){return d.x;})
    .attr("cy",function(d){return d.y;})
    .attr("r",function(d,i){return i*4});

Then I took a step further and created multiple objects with more than a single x and y coordinate (I'm interested in that particular case because my future working dataset [the real one] is made of a series of wind turbines each one with thousands of x-y points).

var dataset = [ {Turbine: "01", x:[100,130,70,100],y:[220,350,60,140]},
                        {Turbine "02", x:[520,120,390,500], y:[300,280,170,400]};

I've got no clue so far of what improvement should be made in the code above in order to work. I realized that d.x and d.y now do not deliver a single x and a single y point, they deliver arrays, that's why the previous code is now useless as attributes cx and cy expect only one coordinate per iteration. I'm trying to find a way to somehow be able to use a new index inside the subselection (for each i in d, the code should then use a ii to get just one point from the subselection d[i].x[ii]).

Any ideas? Thank you for your time in advance!

Upvotes: 0

Views: 160

Answers (1)

floribon
floribon

Reputation: 19183

You need to think about how to translate your real data into a scatter plot. What I'm suggesting, is flatten all your data into individual dots, and differentiate the two Turbines by a different color.

var colors = ['orange', 'green'];

function convertData(dataset) {
  var data = [];
  dataset.forEach(function(oneDataset, datasetIndex) {
    // Split the x and y arrays into pairs
    // (that's assuming oneDataset.x and oneDataset.y are the same length!)
    for (var i=0; i<oneDataset.x.length; i++) {
      data.push({
        x: oneDataset.x[i],
        y: oneDataset.y[i],
        color: colors[datasetIndex]
      });
    }
  });
}

var rawDataset = [ {Turbine: "01", x:[100,130,70,100],  y:[220,350,60, 140]},
                   {Turbine: "02", x:[520,120,390,500], y:[300,280,170,400]};

var dataset = convertData(rawDataset);

Now reuse your "solution 2" code, but with that new color improvement:

var plot = chart
  .selectAll("circle")
  .data(dataset)
  .enter()
  .append("circle")
  .attr("cx",   function(d)   {return d.x;})
  .attr("cy",   function(d)   {return d.y;})
  .attr("r",    function(d,i) {return i*4})
  .attr("fill", function(d)   {return c.color});

This is just one solution. But you will probably need in all cases to "flatten" your long arrays into pairs of coordinates in order to render a scatter.

Upvotes: 2

Related Questions