Giter Club home page Giter Club logo

Comments (10)

mbostock avatar mbostock commented on May 14, 2024

I think it’s time to implement more examples of small multiples, scatterplot matrices, trellis charts, facets, etc. to determine reasonable use cases for parent data and indices.

from d3-selection.

mbostock avatar mbostock commented on May 14, 2024

I think {d, i, nodes} could be a good choice, where nodes is the current group. For example, that makes it easier to select the last node in a selection (i === nodes.length - 1) and to access any ancestors (nodes._parent) or their data.

from d3-selection.

curran avatar curran commented on May 14, 2024

With {d, i, nodes}, how could one access j? It seems to me that for implementing small multiples, the j in {d, i, j} is extremely useful. Here are some examples I have made of small multiples using j:

Conceivably, these small multiples could facet across both X and Y, which would make the k in the proposed {d, i, j, k, ...} args idea useful.

Some ideas for small multiples examples - I could imagine faceting these examples in both X and Y to see what the code might look like:

I feel like the {d, i, j, k, ...} approach would be nice. Or, maybe {d, i, nodes} would be nicer, but I'm just not seeing how to derive what would be j, k, ... from nodes here. One wild guess is that it could look something like this (I'm not sure if/how the index is tracked in the data structure):

var j = nodes._parent._index;
var k = nodes._parent._parent._index;
var l = nodes._parent._parent._parent._index;

from d3-selection.

mbostock avatar mbostock commented on May 14, 2024

The idea is you wouldn’t need to access the other indexes, but I haven’t experimented with it yet, so I can’t say exactly how it would work. :)

from d3-selection.

mbostock avatar mbostock commented on May 14, 2024

I have pushed a mostly-untested implementation to the bilevel branch. I plan on writing tests and experimenting to see how well this new approach works. The implementation is certainly simpler!

from d3-selection.

mbostock avatar mbostock commented on May 14, 2024

I’ve merged the new bilevel selection implementation into master and also simplified how parents are tracked by using a parallel parents array.

A nice property of this new approach is that selection.data can evaluate the values function in exactly the same manner as other selection functions: the values function gets passed {d, i, nodes} where this is the parent node, d is the parent datum, i is the parent (group) index, and nodes is the array of parent nodes (one per group). Also, the parents array can be reused by subselections that do not regroup the selection, such as selection.select, since the parents array is immutable.

This change restricts functionality—in the sense that you cannot access the parent node from within a selection function, nor the parent data, nor the group index—but I believe this is ultimately A Good Thing because it encourages simpler code. Code that depends on parent data or structure (group index) seems inherently more complex than code that doesn’t. Relying on parent data means you can’t simply re-select an element to restore its context: you must re-select the ancestors and then re-select descendants.

Also, flatter selections are more parsimonious: there are already two ways to access parent data. You can push that parent data down into the child data, replicating it for each child. Or you can use selection.each and create a closure that exposes parent and child data simultaneously. This is functionally similar to exposing parent data to every selection method, but you must opt-in. Hopefully this encourages simpler, flatter structures when possible.

Here’s my take on sized donut multiples using this approach:

screen shot 2016-01-20 at 4 30 46 pm

Note that only the arcs need to be drawn within the selection.each context, because only they depend on the parent data to compute the arc radius. The labels do not depend on the parent context, so I’ve moved them outside the each. You could put them inside, of course, but I think it’s probably best to minimize what’s done inside the each to favor flatness.

from d3-selection.

curran avatar curran commented on May 14, 2024

Awesome. Thank you for this example, I didn't realize that selection.each could be used in that way.

from d3-selection.

WardCunningham avatar WardCunningham commented on May 14, 2024

I have struggled with this problem but did not recognize it until your post today. (I solved my problem pushing data down.)

I suspect this will become an important idiom of d3 programming. Is "bilevel selection" the best name? It didn't work for me but it might for others when explained as part of selection.

from d3-selection.

mbostock avatar mbostock commented on May 14, 2024

“Nested selection” is what I normally use. (See also How Selections Work.) I used “bilevel” here to distinguish them from the earlier alpha implementation of arbitrarily-hierarchical selections, where the selections were trees of arbitrary depth rather than limited to one level of grouping. I ultimately found that approach too complicated for too little benefit.

from d3-selection.

curran avatar curran commented on May 14, 2024

Ended up at this issue again after so much water under the bridge!

Here's a snippet I crafter after re-remembering this usage of .each for nesting, I thought it may be useful to others who end up here:

const nested = nest().key(layerValue).entries(data);

let layerGroups = g.selectAll('g.layer').data(nested);
layerGroups = layerGroups.enter().append('g').attr('class', 'layer')
  .merge(layerGroups);

layerGroups.each(function(layerEntry, j) {   
  const circles = select(this)
    .selectAll('circle').data(layerEntry.values);
  circles.enter().append('circle')
    .merge(circles)
      .attr('cx', d => xScale(xValue(d)))
      .attr('cy', d => yScale(yValue(d)))
      .attr('r', d => radiusScale(radiusValue(d)))
      .attr('fill', j === 0 ? 'white' : 'black'); // <---- Access parent index.
});

from d3-selection.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.