Skip to content

Commit

Permalink
imputeLeaf
Browse files Browse the repository at this point in the history
closes #206
  • Loading branch information
Fil committed Jul 19, 2023
1 parent 7bea49e commit b547df5
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 0 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,14 @@ If *path* is specified, sets the path accessor to the given function and returns
d3.stratify().path(d => d)(["a/b", "a/c"]); // nodes with id "/a", "/a/b", "/a/c"
```
<a name="stratify_imputeleaf" href="#stratify_imputeleaf">#</a> <i>stratify</i>.<b>imputeLeaf</b>([<i>impute</i>]) · [Source](https://github.com/d3/d3-hierarchy/blob/main/src/stratify.js), [Examples](https://observablehq.com/@d3/d3-stratify)
If *impute* is specified as a boolean, sets the imputeLeaf option to the given value and returns this stratify operator. Otherwise, returns the current impute option, which defaults to false. If the option is true, a node that has children and a value will be represented as a branching node with no data, with a child node bearing the data. The child node’s id will be the parent id suffixed with a slash.
```js
d3.stratify().path(d => d).imputeLeaf(true)(["a", "a/b"]); // nodes with id "/a", "/a/", "/a/b"
```
### Cluster
[<img alt="Dendrogram" src="https://raw.githubusercontent.com/d3/d3-hierarchy/main/img/cluster.png">](https://observablehq.com/@d3/cluster-dendrogram)
Expand Down
19 changes: 19 additions & 0 deletions src/stratify.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function defaultParentId(d) {
export default function() {
var id = defaultId,
parentId = defaultParentId,
imputeLeaf = false,
path;

function stratify(data) {
Expand Down Expand Up @@ -94,6 +95,20 @@ export default function() {
root.parent = null;
if (n > 0) throw new Error("cycle");

if (imputeLeaf) {
root.each(node => {
if (node.children && node.children.length && node.data != null) {
const child = new Node(node.data);
node.data = null;
child.depth = node.depth + 1;
child.height = 0;
child.parent = node;
child.id = node.id + "/";
node.children.unshift(child);
}
});
}

return root;
}

Expand All @@ -109,6 +124,10 @@ export default function() {
return arguments.length ? (path = optional(x), stratify) : path;
};

stratify.imputeLeaf = function (x) {
return arguments.length ? (imputeLeaf = !!x, stratify) : this.imputeLeaf;
}

return stratify;
}

Expand Down
35 changes: 35 additions & 0 deletions test/stratify-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,41 @@ it("stratify(data) does not treat a falsy but non-empty parentId as the root", (
});
});

it("stratify(data).imputeLeaf(true) imputes leaves when branch nodes have a value", () => {
const s = stratify().path(d => d.path).imputeLeaf(true);
const root = s([
{path: "/gallery", visits: 4},
{path: "/gallery/a", visits: 2},
{path: "/gallery/b", visits: 1}
]);
assert.deepStrictEqual(noparent(root), {
"id": "/gallery",
"depth": 0,
"height": 1,
"data": null,
"children": [
{
"id": "/gallery/",
"depth": 1,
"height": 0,
"data": {"path": "/gallery", "visits": 4},
},
{
"id": "/gallery/a",
"depth": 1,
"height": 0,
"data": {"path": "/gallery/a", "visits": 2}
},
{
"id": "/gallery/b",
"depth": 1,
"height": 0,
"data": {"path": "/gallery/b", "visits": 1}
}
]
});
});

it("stratify(data) throws an error if the data does not have a single root", () => {
const s = stratify();
assert.throws(() => { s([{id: "a"}, {id: "b"}]); }, /\bmultiple roots\b/);
Expand Down

0 comments on commit b547df5

Please sign in to comment.