Lots of examples of using d3.nest function
See it running at http://bl.ocks.org/3176159
Documentation: https://github.com/mbostock/d3/wiki/Arrays
Lots of examples of using d3.nest function
See it running at http://bl.ocks.org/3176159
Documentation: https://github.com/mbostock/d3/wiki/Arrays
id | name | priority | who | time | status | |
---|---|---|---|---|---|---|
T-024 | Organisation list in directory | MUST | Joe | 5 | Complete | |
T-015 | Make term Commissions customisable | MUST | Natasha | 6 | Complete | |
T-016 | Comments popup on select rates | MUST | Mike | 3 | In Progress | |
T-0169 | Upgrade Centos Box | MUST | Joe | 2 | In Progress | |
T-013 | Search in Documents on selected folder | MUST | Natasha | 6 | In Progress | |
T-014 | Separate Document system for LA and Legals | MUST | Joe | 9 | In Progress | |
T-017 | Demo of Look and Feel of Documents front end | MUST | Natasha | 5 | In Progress | |
T-021 | Fix error where forum filename is greater than 100chars | MUST | Mike | 4 | Not Started | |
T-025 | Fix admin so structure of categories displayed | MUST | Mike | 2.5 | Complete | |
T-027 | Reorganise git repos in Assembla | MUST | Joe | 3 | Not Started | |
T-033 | Tree not showing correctly in documents | MUST | Natasha | 1 | In Progress | |
T-052 | Add Cacheing | MUST | Mike | 1.5 | Complete | |
T-055 | Allow custom ordering of document categories | MUST | Joe | 0.5 | Not Started | |
T-056 | Pressing enter on date button triggers cancel | MUST | Joe | 1 | Not Started | |
T-057 | Ajax not working on IE when selecting org | MUST | Natasha | 6 | Not Started | |
T-060 | Send Reminder Email as required | SHOULD | Mike | 3 | Complete | |
T-061 | Attach Document to response in Forum | SHOULD | Joe | 4 | Not Started | |
T-062 | Forum thread notifications | SHOULD | Natasha | 9 | Complete | |
T-063 | Group email notification | SHOULD | Mike | 8 | In Progress | |
T-064 | Admin can see Who is logged in | SHOULD | Joe | 9 | Not Started | |
T-067 | Extend Audit Trail | SHOULD | Natasha | 12 | Complete | |
T-068 | Maintenance Links | SHOULD | Mike | 4 | Complete | |
T-094 | Browse prices button | SHOULD | Joe | 6 | Not Started | |
T-095 | Group email to be only available to the administrator | SHOULD | Natasha | 5 | Complete | |
T-096 | Update cribsheet | COULD | Mike | 2 | Not Started | |
T-0103 | Awarded missing from Estimated Tab | COULD | Joe | 7 | Complete | |
T-0105 | New cribsheet | COULD | Natasha | 7 | Not Started | |
T-0111 | Document not being added on forum response | COULD | Mike | 6 | Not Started | |
T-0114 | Can't delete users once active | WISH | Joe | 3 | Not Started | |
T-0125 | Add course organiser on notification | WISH | Natasha | 2.5 | In Progress | |
T-0126 | Setup demonstration system for Demo | MUST | Joe | 3 | Not Started | |
T-0133 | Fix forum pagination problem properly | MUST | Natasha | 3 | Not Started | |
T-0145 | In Directory, tickbox to select all filtered users | MUST | Joe | 3 | Complete | |
T-0146 | Merge user and user profile in admin | MUST | Natasha | 2 | Not Started | |
T-0147 | Have multiple documents on an estimate | MUST | Mike | 2 | Not Started |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>D3 nest examples</title> | |
<script src="http://d3js.org/d3.v2.js"></script> | |
<script src=" https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> | |
<link href='http://fonts.googleapis.com/css?family=Tienne' rel='stylesheet' type='text/css'> | |
<style> | |
body { | |
font-family: 'Tienne', serif; | |
font-size: 12px; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>D3 Nest Tutorial and examples</h1> | |
<p>Here is my learning process for getting to grips with nest. Discovered the d3 tests half way through which were a great help: <a href="https://github.com/mbostock/d3/blob/master/test/core/nest-test.js">tests</a></p><h2>Simple one level nest</h2> | |
<p>In Bl.ocks.org, click on "Open in a New Window" (bottom right) to view all the examples</p> | |
<p>Group by status</p> | |
<code>var nested_data = d3.nest()<br /> | |
.key(function(d) { return d.status; })<br /> | |
.entries(csv_data);<br /> | |
</code> | |
<textarea id="ex1" rows="15" cols="90"></textarea> | |
<h2>Simple two level nest</h2> | |
<p>Group by status then priority</p> | |
<code>var nested_data = d3.nest()<br /> | |
.key(function(d) { return d.status; })<br /> | |
.key(function(d) { return d.priority; })<br /> | |
.entries(csv_data);<br /> | |
</code> | |
<textarea id="ex2" rows="15" cols="90"></textarea> | |
<h2>Use rollup to count leaves</h2> | |
<p>The leaf level is replaced by a value at the parent level</p> | |
<code>var nested_data = d3.nest()<br /> | |
.key(function(d) { return d.status; })<br /> | |
.key(function(d) { return d.priority; })<br /> | |
.rollup(function(leaves) { return leaves.length; })<br /> | |
.entries(csv_data);<br /> | |
</code> | |
<textarea id="ex3" rows="15" cols="90"></textarea> | |
<h2>Rollup does sums as well</h2> | |
<p>Can't have two rollups, but can return an object/array</p> | |
<code>var nested_data = d3.nest()<br /> | |
.key(function(d) { return d.status; })<br /> | |
.key(function(d) { return d.priority; })<br /> | |
.rollup(function(leaves) { | |
return {"length": leaves.length, | |
"total_time": d3.sum(leaves, function(d) {return parseFloat(d.time);})} })<br /> | |
.entries(csv_data);<br /> | |
</code> | |
<textarea id="ex4" rows="15" cols="90"></textarea> | |
<h2>Rollup everything to get a grand total of number of lines</h2> | |
<p>No key</p> | |
<code>var nested_data = d3.nest()<br /> | |
.rollup(function(leaves) { return leaves.length; })<br /> | |
.entries(csv_data);<br /> | |
</code> | |
<textarea id="ex9" rows="15" cols="90"></textarea> | |
<h2>Sorting</h2> | |
<p>Each level can be sorted by key - a simple ascending or descending...</p> | |
<code>var nested_data = d3.nest()<br /> | |
.key(function(d) { return d.status; }).sortKeys(d3.ascending)<br /> | |
.key(function(d) { return d.priority; }).sortKeys(function(d) { return )<br /> | |
.rollup(function(leaves) { return leaves.length; })<br /> | |
.entries(csv_data);<br /> | |
</code> | |
<textarea id="ex5" rows="15" cols="90"></textarea> | |
<h2>Sorting - custom order</h2> | |
<p>Status, fortuitously, can be sorted in straing ascending order, but Priority requires a custom order. Create an list in the order you want and use indexOf to create the order comparaitor function.</p> | |
<code> | |
var priority_order = ['MUST', "SHOULD", 'COULD', 'WISH'];<br /> | |
var nested_data = d3.nest()<br /> | |
.key(function(d) { return d.status; }).sortKeys(d3.ascending)<br /> | |
.key(function(d) { return d.priority; }).sortKeys(function(a,b) { return priority_order.indexOf(a) - priority_order.indexOf(b); })<br /> | |
.rollup(function(leaves) { return leaves.length; })<br /> | |
.entries(csv_data);<br /> | |
</code> | |
<textarea id="ex6" rows="15" cols="90"></textarea> | |
<h2>Sorting - sort the leaves as well</h2> | |
<p>Use sortValue to sort the leaves - sort by time with smallest first</p> | |
<code> | |
var priority_order = ['MUST', "SHOULD", 'COULD', 'WISH'];<br /> | |
var nested_data = d3.nest()<br /> | |
.key(function(d) { return d.status; }).sortKeys(d3.ascending)<br /> | |
.key(function(d) { return d.priority; }).sortKeys(function(a,b) { return priority_order.indexOf(a) - priority_order.indexOf(b); })<br /> | |
.sortValues(function(a,b) { return parseFloat(a.time) - parseFloat(b.time); } }<br /> | |
.entries(csv_data);<br /> | |
</code> | |
<textarea id="ex7" rows="15" cols="90"></textarea> | |
<h2>Sorting - sort the leaves as well</h2> | |
<p>Use sortValue to sort the leaves - sort by person this time.</p> | |
<code> | |
var priority_order = ['MUST', "SHOULD", 'COULD', 'WISH'];<br /> | |
var nested_data = d3.nest()<br /> | |
.key(function(d) { return d.status; }).sortKeys(d3.ascending)<br /> | |
.key(function(d) { return d.priority; }).sortKeys(function(a,b) { return priority_order.indexOf(a) - priority_order.indexOf(b); })<br /> | |
.sortValues(function(a,b) { return ((a.who < b.who)<br /> | |
? -1<br /> | |
: 1);<br /> | |
return 0;} )<br /> | |
.entries(csv_data);<br /> | |
</code> | |
<textarea id="ex8" rows="15" cols="90"></textarea> | |
<h2>Populate a Select list from csv data</h2> | |
<p>Use nest to get a unique list of people then create a select from it.</p> | |
<code> | |
var nested_data = d3.nest()<br /> | |
.key(function(d) { return d.who}).sortKeys(d3.ascending)<br /> | |
.rollup(function(leaves) { return leaves.length; })<br /> | |
.entries(csv_data);<br /> | |
<br /> | |
var list = d3.select("#ex10").append("select")<br /> | |
<br /> | |
list.selectAll("option")<br /> | |
.data(nested_data)<br /> | |
.enter()<br /> | |
.append("option")<br /> | |
.attr("value", function(d) {return d.key;})<br /> | |
.text(function(d) {<br /> | |
return d.key; });<br /> | |
<br /> | |
</code> | |
<div id="ex10"> | |
</div> | |
<script> | |
d3.csv("./data.csv", function(csv_data){ | |
var nested_data = d3.nest() | |
.key(function(d) { return d.status; }) | |
.entries(csv_data); | |
$("#ex1").html(JSON.stringify(nested_data, null, 3)); | |
var nested_data = d3.nest() | |
.key(function(d) { return d.status; }) | |
.key(function(d) { return d.priority; }) | |
.entries(csv_data); | |
$("#ex2").html(JSON.stringify(nested_data, null, 3)); | |
var nested_data = d3.nest() | |
.key(function(d) { return d.status; }) | |
.key(function(d) { return d.priority; }) | |
.rollup(function(leaves) { return leaves.length; }) | |
.entries(csv_data); | |
$("#ex3").html(JSON.stringify(nested_data, null, 3)); | |
var nested_data = d3.nest() | |
.key(function(d) { return d.status; }) | |
.key(function(d) { return d.priority; }) | |
.rollup(function(leaves) { | |
return {"length": leaves.length, | |
"total_time": d3.sum(leaves, function(d) {return parseFloat(d.time);})} }) | |
.entries(csv_data); | |
$("#ex4").html(JSON.stringify(nested_data, null, 3)); | |
var nested_data = d3.nest() | |
.key(function(d) { return d.status; }).sortKeys(d3.ascending) | |
.key(function(d) { return d.priority; }).sortKeys(d3.descending) | |
.rollup(function(leaves) { return leaves.length; }) | |
.entries(csv_data); | |
$("#ex5").html(JSON.stringify(nested_data, null, 3)); | |
var priority_order = ['MUST', "SHOULD", 'COULD', 'WISH']; | |
var nested_data = d3.nest() | |
.key(function(d) { return d.status; }).sortKeys(d3.ascending) | |
.key(function(d) { return d.priority; }).sortKeys(function(a,b) { return priority_order.indexOf(a) - priority_order.indexOf(b); }) | |
.rollup(function(leaves) { return leaves.length; }) | |
.entries(csv_data); | |
$("#ex6").html(JSON.stringify(nested_data, null, 3)); | |
var priority_order = ['MUST', "SHOULD", 'COULD', 'WISH']; | |
var nested_data = d3.nest() | |
.key(function(d) { return d.status; }).sortKeys(d3.ascending) | |
.key(function(d) { return d.priority; }).sortKeys(function(a,b) { return priority_order.indexOf(a) - priority_order.indexOf(b); }) | |
.sortValues(function(a,b) { return parseFloat(a.time) - parseFloat(b.time); } ) | |
.entries(csv_data); | |
$("#ex7").html(JSON.stringify(nested_data, null, 3)); | |
var priority_order = ['MUST', "SHOULD", 'COULD', 'WISH']; | |
var nested_data = d3.nest() | |
.key(function(d) { return d.status; }).sortKeys(d3.ascending) | |
.key(function(d) { return d.priority; }).sortKeys(function(a,b) { return priority_order.indexOf(a) - priority_order.indexOf(b); }) | |
.sortValues(function(a,b) { return ((a.who < b.who) | |
? -1 | |
: 1); | |
return 0;} ) | |
.entries(csv_data); | |
$("#ex8").html(JSON.stringify(nested_data, null, 3)); | |
var nested_data = d3.nest() | |
.rollup(function(leaves) { return leaves.length; }) | |
.entries(csv_data); | |
$("#ex9").html(JSON.stringify(nested_data, null, 3)); | |
var nested_data = d3.nest() | |
.key(function(d) { return d.who}).sortKeys(d3.ascending) | |
.rollup(function(leaves) { return leaves.length; }) | |
.entries(csv_data); | |
var list = d3.select("#ex10").append("select") | |
list.selectAll("option") | |
.data(nested_data) | |
.enter() | |
.append("option") | |
.attr("value", function(d) {return d.key;}) | |
.text(function(d) { | |
return d.key; }); | |
}); | |
</script> | |
</body> | |
</html> |
This is extremely helpful. Thank you very much for sharing this!
In #ex5 (Sorting) the 2nd sortKeys call contains a function but part of the code is cut off. However, in the code itself you've actually passed it "d3.descending" instead of a function
Thanks for the excellent examples.