Arash Howaida Arash Howaida - 5 months ago 15
JSON Question

D3 Line Generator Handling Multiple Arrays

I have 3 arrays within a JSON file of the following structure:

enter image description here

I am trying to parse a JSON file of coordinate data into something that can be read by D3 path/line generators. I first had to find a way to ensure the values were actual numbers and not strings. A full discussion can be found here:
D3/JS mapping a JSON data callback

That discussion prompted me to not only consider formatting the JSON data via

.map()
to numbers, but also consider a nested/zipped format that the line generator can make sense of. That is really the target I've been after all along. As depicted above, My JSON has 3 arrays,
xs
,
ys
and
id
.
id
only governs color, and takes 1 of 3 values (0,1,2). I was recommended this approach:

var obj = raw_json[0];
var data = obj.id.map((id, i) => [+id, +obj.xs[i], +obj.ys[i]]);


My line generator function is:

var valueLine = d3.svg.line()
.x(function(d) {return xScale(d.xs);})
.y(function(d) {return yScale(d.ys)});


However I am getting tens of thousands of errors, and unfortunately I do not have that much experience with parsing related issues and I am not sure how to proceed.

Full block & JSON here.

Answer Source

Glad to see you took my advice on restructuring your data as we are moving in the right direction. I suggested that you should convert your three separate arrays into one array of individual arrays per point make the use of the line generator more easy and to eliminate the need for cross-array reads to collect data for the points.

This time, though, you are not accessing your values correctly. By using function(d) { return xScale(d.xs); } you are assuming that your points were represented by objects having properties xs and ys. My suggested approach however got rid of these properties by storing the information into arrays. There are basically two ways around this:

  1. Adjust you path generator's .x() and .y() callbacks while keeping your data structure.

    var obj = raw_json[0];
    var data = obj.id.map((id, i) => [+id, +obj.xs[i], +obj.ys[i]]);
    
    // Remember, that d is a point's array [id, x, y]
    var valueLine = d3.svg.line()
      .x(function(d) { return xScale(d[1]); })
      .y(function(d) { return yScale(d[2]); });
    
  2. If you prefer to store your points' data in objects instead, another solution would be to adjust how your data is built.

    // Structure data into an array of objects {id, x, y}
    var obj = raw_json[0];
    var data = obj.id.map((id, i) => ({
      id: +id,
      x:  +obj.xs[i],
      y:  +obj.ys[i]
    }));
    
    // Keep your code as d now has properties x and y.
    var valueLine = d3.svg.line()
      .x(function(d) { return xScale(d.x); })
      .y(function(d) { return yScale(d.y); });