On this page

Linked category panels

Experimental: the API may change.

Split a line, bar or scatter view into ordered category panels while keeping selection linked by row ID. FacetView was introduced in the 4.0.0.dev1 preview and is available under inklet.experimental.browser.

Six linked panels of simulated monthly revenue and profit for North, South and West

Open the interactive figure · Complete Python recipe

The recipe uses 36 original simulated monthly rows, with three invented business categories. The first row of panels shows revenue; the second shows signed profit. Every category uses the same revenue domain and the same profit domain; month positions align across both rows of panels. North has missing revenue in June and zero profit in October. These are illustrative values, not company accounts. Category labels identify the panels; the explanation stays outside the artwork.

Explore the figure

  1. Click North's negative March profit bar. The incident revenue segments in North's panel highlight the same north-03 row. Other categories stay separate.
  2. Search for North. The South and West panels retain their axes and category labels, so filtering does not move the remaining panels. Clear the search.
  3. Switch between SVG, canvas and hybrid display, then download vector SVG. All three use the same compiled geometry and row selection.
  4. Expand Data revision and apply North and South only. West's panels remain present and empty. If you selected a West row, the default missing-ID policy rejects its removal; choose Drop removed IDs to transfer the view and inspect the report. Retained revenue and profit values do not change.

Selecting a line chooses an endpoint row. A valid row with no neighboring valid observation has no line segment but remains available in its bar panel or table. The linked plot guide documents picking and filtering details.

Define categories explicitly

from inklet.experimental.browser import BrowserFigure, FacetView, LineView
from inklet.selection import KeyedTable

table = KeyedTable("observations", {
    "id": ["n1", "s1", "n2", "s2"],
    "region": ["North", "South", "North", "South"],
    "month": [1, 1, 2, 2],
    "revenue": [42, 35, 45, 37],
})
figure = BrowserFigure(table, [
    FacetView(
        LineView("revenue", "month", "revenue", (1, 12), (30, 80),
                 x_label="Month", y_label="Revenue / kEUR"),
        column="region",
        values=("North", "South", "West"),
    ),
], width=240, columns=3)

values supplies the exact category order. Each value must be a unique nonempty string. Optional labels=(...) provides display labels in the same order and with the same length; omitting labels displays the values themselves. The underlying category column contains strings or None. Category labels are measured with the figure's text layout; they are included in vector export.

Empty categories retain their panels. Null categories and strings absent from values remain in the global keyed table but produce no marks in that facet group. They can still be selected through the table or another view. Inspect figure.payload()["facet_groups"]: each entry reports its name, column, ordered values and unassigned_ids. These rows are not silently reassigned to an automatic “Other” category.

The browser lists unassigned source IDs under Rows outside facet categories. This diagnostic updates when switching data revisions. It describes the source table, independently of the current visibility filter.

Facet figures share measured plot margins across the whole grid, so equal domains also have equal physical scales across their panels. Empty panels reserve the same space. Ordinary documents can opt into the same rule with document(..., share_plot_margins='all').

document(..., share_plot_margins=True) or subfigure(..., share_plot_margins=True) aligns plots without reserving every plot's furniture on every other plot. Left and right furniture is shared along vertical grid lines: stacked plots whose cells start on the same grid line reserve the largest left furniture among them, and stacked plots whose cells end on the same grid line reserve the largest right furniture among them, so their data edges line up. Plots are stacked when their rows touch. A long label in one column does not narrow plots that share neither of its grid lines. Top and bottom furniture is shared along each row, and every row adds its own furniture to the tallest natural data region; a legend or colorbar under one row adds no space under the others. A fixed page height keeps these rows and gives extra space to plot rows in proportion to their data heights. Fixed artwork retains its authored size. This option defaults to False.

The wrapped view supplies fixed domains, axis labels, color and mark settings. Line adjacency follows source order within each category, so interleaving North and South rows does not join their lines or break either series. Null x/y pairs break a category's line. Filtering removes segments incident to hidden rows; it never reconnects surviving observations across a removed row. Inklet does not sort, aggregate or interpolate the table.

The statistical preview also supports faceted ECDF and interval views. ECDF populations are calculated per category and remain fixed during filtering; supplied interval bounds are not recalculated.

BrowserFigure accepts one to four view definitions, expanding to at most twelve panels. Plain views and facets can share a figure. The default layout uses at most two columns; set columns=1 through 4 explicitly to control the grid. Facets wrap ScatterView, LineView, BarView, ECDFView or IntervalView; geographic region facets, nested facets and automatic category discovery are outside this preview.

Save, replace and reconstruct

python examples/v4/faceted_operations.py --output out/v4-facets

# Reopen a view saved while all three regions were active.
python examples/v4/faceted_operations.py --state /path/to/view.json \
  --output out/v4-restored

# Reopen a view saved after switching to North and South only.
python examples/v4/faceted_operations.py --without-west \
  --state /path/to/revised-view.json --output out/v4-restored

The script writes an offline index.html, vector figure.svg and view.json. The HTML opens with the saved selection, filter and page viewport applied; the SVG reconstructs the same state in Python. Saved-state loading requires the exact data and measured scene revision.

Use replace_data() or an embedded RevisionOption to transfer selections to revised data explicitly. Facet definitions are retained, including categories that lose all their rows. The data replacement guide explains removed-ID handling and viewport policies. This example embeds both cohorts, requires no external requests and credits its simulated data in the page footer.

SeriesView also supports facets, with each entity's complete sample sequence contained in its category panel.

Search documentation

Type to search guides, examples and the API.