Slicing
AI assisted, human approved — novem uses AI to review and keep our documentation up to date.
The Novem slicing instruction is modelled on the python array slicing notation, but expanded with a few quality of life enhancements. The goal of slicing is to provide an easy way to subdivide your data for applying styles and formatting — and the SAME notation, with the same meaning, is used by every config file: table cells, chart colors, mark types, labels, marks, facets and legends.
In addition for the primary slicing function, we also allow the user to supply
a comma separated list of indices starting at zero. (Negative indices count
from the end in colon slices such as -1: and as a single bare index, but not
inside a comma-separated list.)
Syntax
The novem slicing syntax is created to operate on sub-sections of tables. To achieve this we need two slices, one for rows and one for columns. These two slicers together is called a selector.
Any styles using selectors apply to the intersection of the two slices — the block of cells where the selected rows and columns cross.
Slicers
The slicing operation consists of one or more integers separated by a colon :. The first number denotes the starting
position (counting from zero), the second the ending position and the third the step (how many items to skip). The
integer values can be skipped to indicate start or end of a range.
Selectors
For a complete selector, a slice is specified twice, once for rows and once for columns. The instructions are separated with a space.
Below are a few examples of selectors along with some explanations.
-- select all rows and all columns
: :
-- select first row and all columns
0 :
-- select last row and all columns
-1 :
-- select first three rows
0:2 : -- 2 is the third element (zero-indexed), and the stop is INCLUSIVE
-- select last three rows
-3: :
-- select a 3x3 matrix in the top left corner of the table
0:2 0:2
:2 :2 -- the zero is implied if omitted
-- select every other row in the table
::2 :
-- select the first and last row
0,-1 :
-- select row 4,5,6
3,4,5 : -- remember zero index
One index space: the raw file
Every selector addresses the raw uploaded file: (0,0) is the
very first value of your csv. Row 0 is the header line, column 0
the leftmost column — on a table you can style them like any other
cell.
Charts use the exact same coordinates. Column 0 is the x /category
column and row 0 the header line; neither carries a paintable mark,
so a selector that lands there simply paints nothing. In practice:
the first series is column 1, the first data point row 1, and a
line that works on a table means the same cells on a chart of the
same csv. Pie and donut slices are rows — 2 : addresses the second
slice.
Two spaces are deliberately not the csv, because they only exist after layout: facet strip-label cells and per-panel margins address the physical panel grid, and the axis grammar's third slot addresses positions in the generated tick sequence. They still use the same slicer vocabulary.
One slicer
A line with a single slicer addresses columns: revenue b bolds
the revenue column, 1 red colors the first series. Two slicers are
always rows × columns, and the two-slicer reading wins whenever both
leading tokens parse as slicers.
Header names
A column slicer can use the column's name instead of its index:
revenue, big_cat (spaces read as underscores, case-insensitive).
Names work inside ranges and lists — revenue:costs, q1,q3 — and
resolve to the column's raw position. Digits always win: a header
literally named 2024 never hijacks the positional selector 2024.
Row selectors are always positional.
Edge semantics
- Stop is inclusive:
0:2is three rows (the pandas.locrule). - Overflows are inclusive:
:1000on 100 rows is all 100,-500:on 50 rows is all 50. Only a window entirely outside the axis —100:200on 5 rows, or a reversed range like3:1— selects nothing. - Negatives count from the end:
-1is the last row; an over-negative single index (-99on 3 rows) selects nothing. - Junk selects nothing. A selector that fails to parse drops its line — it never degrades to "everything". In comma lists, invalid items drop individually and the rest survive.
Line markers: + and -
In the chart grammars (type,
labels, marks, colors) and the
table styling and format files, a + or - as the FIRST character
of a line, followed by a space, is a line marker:
+ <selector> [overrides]restates the nearest preceding line over a new selection —l:%v le:tthen+ 3puts the same label on another series.- <selector>erases those cells from every line above it, and later lines still paint into the hole.
Attached signs always belong to the slicer: -1 red colors the last
column, - 1 erases column 1. Table styling and format files take
the same markers: a bare - or + as the first token of a line is
always a marker there too, and the historical tolerant reading of a
bare leading - is retired. On a + line whose tokens are all
slicer-shaped the tokens read as the new selector; when a
slicer-shaped payload is meant (the align dash), write the row
slicer explicitly (+ : 1 -).
Try it out!
Play around with a live demo of the slicer syntax:
Examples
Below are a couple of examples showing how the slicer selection can be used to apply different styles to a novem table.
Slicers and steps
This example shows a static color pattern reminiscent of a picnic blanket using three shades of blue and setting the background color.
We use four selectors and leverage the step instruction. First color alternating rows starting at different offsets, then add alternating columns. The selectors are applied in order, so later entries take precedence.
-- Create a "picnic blanket" using 4 shades of blue
::2 : bg blue-100 -- color every other row starting at 0
1::2 : bg blue-200 -- color every other row starting at 1
1::2 1::2 bg blue-300 -- color every other col starting at row 1 col 1
::2 1::2 bg blue-200 -- color every other row starting at row 0 col 1
Index lists
Here we highlight a hierarchical structure in our table by coloring rows in descending shades of gray. This is a common strategy when wanting to preserve space.
Unlike in the picnic example above, here we explicitly choose which entries to highlight with a comma-separated list of rows.
-- Color rows by "hierarchy"
1 : bg gray-500 -- world
2,5,8 : bg gray-400 -- region 1
3,6,9,12,19 : bg gray-300 -- region 2