Hierarchical charts
sunburst, treemap and icicle are px.sunburst, px.treemap and px.icicle: one sunburst, treemap or icicle trace from a table. The tree comes either from a path of columns, which Express turns into nodes for you, or from columns that already name each row's parent (names and parents). The three functions take the same options.
From a path of columns
path lists columns from the root level down, one level per column. Every row is a leaf, and every distinct path prefix is a node: ['continent', 'country'] makes a node per continent with its countries below it. Values are summed up the tree, and the trace gets branchvalues: 'total', so each branch is exactly as big as its children.
express/sunburst-pathimport hx from '@mk7s/holochart-express';
declare const rows: object[]; // [{ continent: 'Asia', country: 'Japan', pop: 1.27e8, lifeExp: 82.6 }, …]
hx.sunburst(rows, { path: ['continent', 'country'], values: 'pop', color: 'lifeExp' });
hx.treemap(rows, { path: ['continent', 'country'], values: 'pop' });
hx.icicle(rows, { path: ['continent', 'country'] }); // no values: sized by row countsWhat Express builds, as plotly.py's process_dataframe_hierarchy does:
- Nodes, from the leaves up, each level in the order its values first appear. A node's
labelsentry is its value, itsidsentry the path joined by/(Asia/Japan), and itsparentsentry its parent's id (''for the top level). - Values: the
valuescolumn summed per node, missing values counting as 0. Withoutvalues, each row counts 1, in a column namedcount(count=%{value}on hover). - Missing entries end a row's path early, making it a leaf higher up: a row with a continent and
country: nullis a leaf on the first level. A missing entry can't have a present one after it, and a row can't stop at a node that other rows continue below; both throw. - Hover text lists
labels, the values column,parentandid, then the color andhoverDatacolumns, as px writes it.
A column of the same value in every row puts one root above the first level (px's px.Constant('World')); pass it as an array:
import hx from '@mk7s/holochart-express';
declare const rows: { continent: string; country: string; pop: number }[];
hx.icicle(rows, { path: [rows.map(() => 'World'), 'continent', 'country'], values: 'pop' });express/icicle-pathColors
A numeric color goes through a colorscale: leaves take their row's value and every branch the mean of its children's rows, weighted by values (by row count without values). The colorscale (colorContinuousScale, rangeColor, colorContinuousMidpoint) and its colorbar, titled with the column's label, are on layout.coloraxis (the trace's marker.coloraxis refers to it), as in px.
Any other color column colors nodes by category, from the colorway (or colorDiscreteSequence) or colorDiscreteMap. A branch takes its rows' value when they all agree and '(?)' when they don't; give '(?)' its own color in colorDiscreteMap. The nodes are sorted by color, so '(?)' takes the first color of the sequence when not mapped.
express/treemap-pathimport hx from '@mk7s/holochart-express';
declare const tips: object[]; // [{ day: 'Fri', time: 'Lunch', sex: 'Male', total_bill: 16.99 }, …]
hx.treemap(tips, {
path: ['day', 'time', 'sex'],
values: 'total_bill',
color: 'time',
colorDiscreteMap: { '(?)': 'gray', Lunch: 'gold', Dinner: 'darkblue' },
});The color column is added to the hover label (through customdata) unless hoverData hides it (hoverData: { lifeExp: false }). hoverName, hoverData and customData columns are aggregated like a categorical color: a branch shows the value its rows share, or '(?)'. A hoverData column that is also values is summed.
Without color, the first level takes the colorway and deeper nodes their parent's color, as the traces do; colorDiscreteSequence also becomes layout.sunburstcolorway (treemapcolorway, iciclecolorway).
From names and parents
When the table already names each row's parent, pass the columns through: names (the labels), parents, and ids when labels repeat. values are taken as given, and branchvalues is the trace's default ('remainder') unless you set it.
express/sunburst-parentsimport hx from '@mk7s/holochart-express';
const budget = [
{ item: 'Budget', parent: '', amount: 1000 },
{ item: 'Engineering', parent: 'Budget', amount: 520 },
{ item: 'Platform', parent: 'Engineering', amount: 240 },
{ item: 'Sales', parent: 'Budget', amount: 280 },
];
hx.sunburst(budget, { names: 'item', parents: 'parent', values: 'amount', branchvalues: 'total' });path and ids / parents are exclusive: pass one or the other.
Options
| Option | px | What it does |
|---|---|---|
path | path | Columns of the levels, root first; builds ids, labels, parents |
names, parents, ids | names, parents, ids | Columns of labels, parent ids and ids (without path) |
values | values | Node sizes; summed per node with path |
color | color | Node colors: a colorscale when numeric, else categories |
colorContinuousScale, rangeColor, … | color_continuous_scale, range_color, … | The colorscale of a numeric color |
colorDiscreteSequence, colorDiscreteMap | color_discrete_sequence, color_discrete_map | Category colors; '(?)' for mixed branches |
hoverName, hoverData, customData | hover_name, hover_data, custom_data | Hover text and custom data, aggregated per node with path |
branchvalues | branchvalues | 'total' (default with path) or 'remainder' |
maxdepth | maxdepth | Levels drawn from the root down |
Plus labels, title, template, width and height, as every function. Draw the figures with traces-hier (register(...hierTraces)), or the @mk7s/holochart bundle.
Differences from plotly.express
- Aggregated
hoverName,hoverDataandcustomDatavalues keep their type (numbers stay numbers, so hover formats apply); px turns them into strings. - Without
values, the count column iscount, orcount_1, … when the data has acountcolumn (px joins the column names). px.Constantisn't offered: pass an array of one repeated value as a path column.