UNPKG

supergroup

Version:

Nested groups on arrays of objects where groups are Strings that know what you want them to know about themselves and their relatives.

153 lines (137 loc) 7.75 kB
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <base data-ice="baseUrl" href="../"> <title data-ice="title">Overview</title> <link type="text/css" rel="stylesheet" href="css/style.css"> <link type="text/css" rel="stylesheet" href="css/prettify-tomorrow.css"> <script src="script/prettify/prettify.js"></script> <script src="script/manual.js"></script> </head> <body class="layout-container manual-root" data-ice="rootContainer"> <header> <a href="./">Home</a> <a href="./manual/index.html" data-ice="manualHeaderLink">Manual</a> <a href="identifiers.html">Reference</a> <a href="source.html">Source</a> <a data-ice="repoURL" href="https://github.com/Sigfried/supergroup.git" class="repo-url-github">Repository</a> <div class="search-box"> <span> <img src="./image/search.png"> <span class="search-input-edge"></span><input class="search-input"><span class="search-input-edge"></span> </span> <ul class="search-result"></ul> </div> </header> <nav class="navigation" data-ice="nav"><div class="manual-toc-root"> <div data-ice="manual" data-toc-name="overview"> <h1 class="manual-toc-title"><a href="manual/overview.html" data-ice="title">Overview</a></h1> <ul class="manual-toc"> <li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="manual/overview.html#supergroup-js" data-ice="link">Supergroup.js</a></li> </ul> </div> <div data-ice="manual" data-toc-name="reference"> <h1 class="manual-toc-title"><a href="identifiers.html" data-ice="title">Reference</a></h1> <ul class="manual-toc"> <li data-ice="manualNav" class="indent-h1"><span class="manual-dot"></span><a href="identifiers.html#class" data-ice="link">Class</a></li> </ul> </div> </div> </nav> <div class="content" data-ice="content"><div class="github-markdown"> <div class="manual-breadcrumb-list"> <a href="./manual/./index.html">Manual</a> <span>&#xBB;</span> <span data-ice="title">Overview</span> </div> <div data-ice="content"><h1 id="supergroup-js">Supergroup.js</h1> <p>Supergroup brings extreme convenience and understandability to the manipulation of Javascript data collections, especially in the context of D3.js visualization programming.</p> <p>As if in submission to the great programmers commandment--<em>Don&apos;t Repeat Yourself</em>--every time I find myself writing a piece of code that solves basically the same problem I&apos;ve solved a dozen times before, a little piece of my soul dies.</p> <p>Utilities for grouping record collections into maps or nests abound: <a href="https://github.com/mbostock/d3/wiki/Arrays#-nest">d3.nest</a>, <a href="https://github.com/mbostock/d3/wiki/Arrays#associative-arrays">d3.map</a>, <a href="http://underscorejs.org/#groupBy">Underscore.groupBy</a>, <a href="https://github.com/iros/underscore.nest">Underscore.Nest</a>, to name a few. But after these tools relieve us of a certain amount of repetitive stress, we&apos;re often left with a tangle of hairy details that fill us with a dreadful sense of deja vu. Supergroup may seem like the kind of tacky wonder gadget you&apos;d find on a late-night Ronco ad, but, for the low, low price of free, it makes data-centric Javascript programming fun again. <strong>And</strong>, when you find yourself in a D3.js callback routine holding a datum object that might have come from anywhere--for instance, with a tooltip callback used on disparate object types--everything you want to know about your object and its associated metadata and records is right there at your fingertips.</p> <p>Just to be clear about the problem&#x2014;you start with tabular data from a CSV file, a SQL query, or some AJAX call:</p> <p><div><div class="label">Some very fake hospital data in a CSV file...</div> <pre class="rendercode language-javascript" id="csv"><code> tabulate(d3.select(&apos;pre#csv&apos;), data, [&apos;Patient&apos;,&apos;Patient Age&apos;,&apos;PatientVisit&apos;,&apos;Date&apos;,&apos;Time&apos;,&apos;Unit&apos;,&apos;Physician&apos;,&apos;Charge&apos;,&apos;Copay&apos;,&apos;Insurance&apos;,&apos;Inpatient&apos;]); // # run </code></pre></div> </p> <p><div><div class="label">...turned into canonical array of Objects (using d3.csv, for instance)</div> <pre class="rendercode language-javascript" height="150px"><code> data; // # render result.replace(/{/g,&apos;\n {&apos;).replace(/]/,&apos;\n]&apos;); </code></pre></div> </p> <p>Without Supergroup, you&apos;d group the records on the values of one or more fields with a standard grouping function, giving you data like:</p> <p><pre class="rendercode language-javascript" id="nestmap" height="150px"><code> d3.nest().key(function(d) { return d.Physician; }) .key(function(d) { return d.Unit; }) .map(data); // # show render indent2 </code></pre> </p> <p>or</p> <p><pre class="rendercode language-javascript" id="nestentries" height="150px"><code> d3.nest().key(function(d) { return d.Physician; }) .key(function(d) { return d.Unit; }) .entries(data); // # show render indent2 result.replace(/,\n/g, &quot;, &quot;).replace(/(&quot;key&quot;.<em>, )/g,&quot;$1\n&quot;).replace(/, </em>/g, &quot;, &quot;) </code></pre> </p> <p>To my mind, these are awkward data structures (not to mention the awkwardness of the calling functions.) The <code>map</code> version looks ok in the console, but D3 wants data in arrays, not as objects. The <code>entries</code> version gives us arrays of key/value pairs, but on upper levels <code>values</code> is another array of key/value pairs while on the bottom level <code>values</code> is an array of records. In both <code>entries</code> and <code>map</code>, you can&apos;t tell from a node at any level what dimension was being grouped at that level. </p> <p>Supergroup gives you almost everything you&apos;d want for every item in your nest (or in your single array if you have a one-level grouping):</p> <ul> <li>An array of the values grouped on (could be strings, numbers, or dates) (<a href="#basics:aplainarrayofstringsenhancedwithchildrenandrecords">Basics</a>)</li> <li>The records associated with each group</li> <li>Parents of nested groups (<a href="#dimensionnamesandpaths">Dimension Names and Paths</a>)</li> <li>Immediate child groups if any</li> <li>All descendant groups (<a href="#retrievingsetsofvalues">Retrieving sets of values</a>)</li> <li>Only descendant groups at the leaf level</li> <li>For a group at any level, the name of the dimension (attribute, column, property, etc.) grouped on</li> <li>Path of group names from root to current group</li> <li>Path of group dimension names from root to current group</li> <li>Aggregate calculations on records for that group and its descendants (<a href="#aggregates">Aggregates</a>)</li> <li>Ability to look up specific values (<a href="#findingspecificvalues">Finding specific values</a>)</li> <li>Any of these in a format D3 or some other tool expects (<a href="#usingsupergroupford3hierarchylayouts">Using Supergroup for D3 hierarchy layouts</a>)</li> <li>Ability to include records in multiple groups if appropriate (<a href="#multi-valuedgroups">Multi-valued Groups</a>)</li> </ul> </div> </div> </div> <footer class="footer"> Generated by <a href="https://esdoc.org">ESDoc<span data-ice="esdocVersion">(0.4.3)</span></a> </footer> <script src="script/search_index.js"></script> <script src="script/search.js"></script> <script src="script/pretty-print.js"></script> <script src="script/inherited-summary.js"></script> <script src="script/test-summary.js"></script> <script src="script/inner-link.js"></script> <script src="script/patch-for-local.js"></script> </body> </html>