Hierarchical charts
.qp.network.format
Format a table to be in the shape expected by the graph layout algorithm
Parameters:
Name | Type | Description |
---|---|---|
t | table | Table to format |
c | symbol[] | Pair of symbols indicating the id and child columns |
Returns:
Type | Description |
---|---|
table | Formatted table |
.qp.network.layout
Perform a force-directed layout on the given table
Parameters:
Name | Type | Description |
---|---|---|
t | table | Table to layout |
x | symbol | ID column |
y | symbol | Child column |
o | null | dict (decay: float; speed: long; ticks: long; c: float; maxdepth: long; theta: float) | Options to control the layout |
Returns:
Type | Description |
---|---|
table | Edge-table with original node properties added in |
Example: Basic network
g: .gg.cheat.i.assemble[];
layout: .qp.network.layout[g; `id; `children; ::];
.qp.theme[.gg.theme.blank]
.qp.stack (
.qp.segment[layout;`px__;`py__;`ppx__;`ppy__;::];
.qp.point[layout;`px__;`py__;::])
.qp.tree.layout
Layout for a hierarchical tree. An implementation of Reingold and Tilford's layout.
The layout results in a node table and an edge table. These tables can be used in a point and segment geometry to draw the tree (see the examples below).
Options:
- [
`inverty
] whether the y axis should be inverted (useful for plotting horizontally or radially).
Parameters:
Name | Type | Description |
---|---|---|
t | table | table of a tree - should contain a scalar id column and a nested child column pointing to other ids |
id | symbol | id column |
children | symbol | children column |
o | dict | null | options |
Returns:
Name | Type | Description |
---|---|---|
<returns> | dict | Node and edges layout table |
<returns>.nodes | table | |
<returns>.edges | table |
Example: Basic tree example
// Data has a nested child column
t: .gg.cheat.i.assemble[];
l: .qp.tree.layout[t;`id;`children;::];
.qp.theme[.gg.theme.blank]
.qp.stack (
.qp.segment[l`edges;`x__;`y__;`x2__;`y2__;::];
.qp.point[l`nodes;`x__;`y__;::])
Example: Radial tree (polar coordinates)
l: .qp.tree.layout[t;`id;`children;``inverty!(::;1b)];
.qp.theme[.gg.theme.blank]
.qp.stack (
.qp.segment[l`edges;`y__;`x__;`y2__;`x2__]
.qp.s.coord .gg.coords.polar;
.qp.point[l`nodes;`y__;`x__;::])
Example: horizontal tree
l: .qp.tree.layout[t;`id;`children;``inverty!(::;1b)];
.qp.theme[.gg.theme.blank]
.qp.stack (
.qp.segment[l`edges;`y__;`x__;`y2__;`x2__;::];
.qp.point[l`nodes;`y__;`x__;::])
.qp.treemap.layout
Square space-filling tree map layout algorithm. The result is a table of rectangle positions. This can be joined to a table to display more information, or just visualized using a .qp.rect geometry as in the example below.
For a multi-level treemap, pass in the bounding rect of the next-level. See an example below for a two-level treemap.
Options:
- [
`x__`y__`x2__`y2__
] bounding rect for a multi-level treemap (output of a previous run) - [
`pad
] whether to add a padding the each rectangle, false be default
Parameters:
Name | Type | Description |
---|---|---|
t | table | |
x | symbol | Category/label column |
y | symbol | Numeric column |
o | dict | null | options |
Returns:
Type | Description |
---|---|
table | treemap rectangle positions keyed by their label |
Example: Basic treemap
t: ([]Sector: 10?`8;MarketValue: 10?100);
positions: .qp.treemap.layout[t; `Sector; `MarketValue; ::];
//=> Sector | x__ y__ x2__ y2__
//=> --------| -----------------------------------
//=> cjfagcid| 0 0 33.4608 53.14286
//=> hjfkgael| 0 53.14286 33.4608 100
//=> ...
.qp.theme[.gg.theme.blank]
.qp.rect[positions;`x__;`y__;`x2__;`y2__]
.qp.s.aes[`fill; `Sector] ,
.qp.s.geom[``colour!(::;0xffffff)]
Example: Two-level treemap
// Initial space fill of top-level hierarchy
initialLayout: 0!.qp.treemap.layout[t;`Sector;`MarketValue;``pad!(::;1b)];
// Divide each of the above with the next level
// -- Just using random data for example
subsectors: {([]Subsector: 50?`8;MarketValue: 50?100)} each til count t`Sector;
positions: raze {
@[;`Sector;:;x] 0!.qp.treemap.layout[y; `Subsector; `MarketValue; z]
}'[t`Sector; subsectors; initialLayout];
// Add back in the market value of each subsector
positions: raze[subsectors] lj `Subsector xkey positions;
.qp.theme[.gg.theme.blank]
.qp.rect[positions;`x__;`y__;`x2__;`y2__]
.qp.s.geom[``colour`alpha!(::;0xffffff;0xae)] ,
.qp.s.aes[`fill`alpha; `Sector`MarketValue]
.qp.treestack.layout
Layout for a hierarchical tree. A stack tree layout. Output is x, y, x2, y2 coordinates for .qp.rect.
Useful for weighted trees (trace timelines, etc). When used in polar coordinates, becomes a Sunburst Chart.
Options:
- [
`expand
] expand children to take entire width of the parent. - [
`filldepth
] depth at which children are assigned a colour (default 4). - [
`colours
] a list of 0xrrggbb colours to use when filling.
Parameters:
Name | Type | Description |
---|---|---|
t | table | table of a tree - should contain a scalar id column and a nested child column pointing to other ids |
id | symbol | id column |
children | symbol | children column |
weight | symbol | weight (numeric) column |
o | dict | null | options |
Returns:
Name | Type | Description |
---|---|---|
<returns> | dict | Node and edges layout table |
<returns>.nodes | table | |
<returns>.edges | table |
Example: Basic layout
t: .gg.cheat.i.assemble[];
t: update w:count each children from t;
rr: .qp.treestack.layout[t;`id;`children;`w;``expand!(::;1b)];
.qp.rect[rr;`x__;`y__;`x2__;`y2__]
.qp.s.geom[``colour!(::;0xffffff)]
Example: Adding a fill and alpha scale
.qp.theme[.gg.theme.blank , ``legend_use!(::;0b)]
.qp.rect[rr;`x__;`y__;`x2__;`y2__]
.qp.s.geom[``colour!(::;0xffffff)] ,
.qp.s.aes[`fill`alpha; `id`d__] ,
.qp.s.scale[`fill; .gg.scale.colour.cat rr[`id]!rr`fill__]
Example: Sunburst chart
.qp.theme[.gg.theme.blank]
.qp.theme[``legend_use!(::;0b)]
.qp.rect[rr;`y__;`x__;`y2__;`x2__]
.qp.s.geom[``colour!(::;0xffffff)] ,
.qp.s.aes[`fill`alpha; `id`d__] ,
.qp.s.scale[`fill; .gg.scale.colour.cat rr[`id]!rr`fill__] ,
.qp.s.coord[.gg.coords.polar]