Groups and rows from nested data

I want to draw multiple svg lines (using D3.js) from a nested object structure like:

data = [ 
{ Name: "jim", color: "blue", Points: [{x:0, y:5 }, {x:25, y:7 }, {x:50, y:13}] },
{ Name: "bob", color: "green", Points: [{x:0, y:10}, {x:25, y:30}, {x:50, y:60}] }
];

var line_gen = d3.svg.line().interpolate("linear")
                .x(function(d){return d.x;})
                .y(function(d){return d.y;}); 

      

My first attempt, based on this question , was to use svg: g to represent the first nesting level, then access the second nesting level in the group to display the string:

var g = svg.selectAll(".linegroup")
.data(data).enter()
.append("g")
.attr("class", "linegroup")
.style("stroke", function(d) { return d.color; })
.style("fill", "none");

g.selectAll(".line")
.data(function(d) { return d.Points;})
.enter().append("svg:path")
  .attr("d", line_gen);

      

But it didn't produce any lines. Instead, within each group, I got an empty path tag for each of the three data points. It looks like the data form is causing problems.

<g class="linegroup" style="stroke: #0000ff; fill: none;">
    <path></path>
    <path></path>
    <path></path>
</g>

      

I found one solution (post as an answer) that doesn't use groups, but I'd still like to know why the grouped solution doesn't work.

+3


source to share


2 answers


Here's an answer mostly based on that question , except it doesn't use d3.entries:

data = [ 
{ Name: "jim", color: "blue", Points: [{x:0, y:5 }, {x:25, y:7 }, {x:50, y:13}] },
{ Name: "bob", color: "green", Points: [{x:0, y:10}, {x:25, y:30}, {x:50, y:60}] }
];

svg = d3.select("body").append("svg:svg").attr("width", 100).attr("height", 100)

var line_gen = d3.svg.line().interpolate("linear")
                .x(function(d){return d.x;})
                .y(function(d){return d.y;});

svg.selectAll(".line")
  .data(data)
  .enter().append("svg:path")
    .attr("d", function(d) { return line_gen(d.Points); })   // <<<
    .style("stroke", function(d) { return d.color; })
    .style("fill", "none");

      



The key approach here is not to return the line_gen function directly to the "d" attribute, but to move it to another function that passes the correct nested array from the external object.

See also the excellent discussion on d3.entries vs. d3.values. d3.entries seems to offer a lot for similar problems, but I don't think it really helps in my case.

+2


source


The reason is that you want to draw a line for each item in your list. Nested selections are for cases where there are more levels. For example, if you have a list with lists as items, and each item in the list contains a set of paths (for example, for grouping sets of curves), nested selections would be fine.



What happens in your case is that d3 creates a new path for each element Points

- that is, one for each point.

+1


source







All Articles