Comments (10)
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.
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.
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.
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.
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.
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:
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.
Awesome. Thank you for this example, I didn't realize that selection.each could be used in that way.
from d3-selection.
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.
“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.
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)
- How to add passive listener into zoom event? HOT 1
- Proposal: add sample code for transitions into README docs HOT 1
- How to report type issues HOT 1
- d3.style('padding') or d3.style('margin') returned empty string only in firefox HOT 2
- Adopt InternMap for selection.data
- Stash the key used by the previous data-join HOT 2
- Raise an error when passing a `selection.data()` key that does not evaluate to a string. HOT 1
- Selection.one HOT 12
- Please provide your artifact as transpiled (CJS) code. HOT 3
- Enable the use of d3.join() without implicit d3.order() call HOT 3
- selection.appendAll HOT 3
- Is anyone working on D3.ts ? HOT 1
- chaining multiple transform styles to an element do not all get applied to the element HOT 1
- Proposal: Memoization Utility HOT 4
- Error: path attribute d expected number, on value with scientific notation HOT 2
- Chaining select has a side-effect on data HOT 1
- `pointer.js` function is not available for import through `d3-selection` HOT 8
- .attr on null selection should not error HOT 3
- Missing null check HOT 1
- Cannot import {pointer} function as it is not available to import HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from d3-selection.