Step Matrix

Heatmap of what users are doing at each step of their path: cell [event, step] is the share of paths on that event at that step, so every column sums to 1 (to 0 in diff mode). Rows are events, columns are steps from the anchor — path_start by default, or a path_pattern event, in which case the columns to its left are negative.

Same numbers as Step Sankey, drawn as a table.

How it works

Stack every path up, slice the stack by step, and count: what share of paths is sitting on each event at step 1, at step 2, and so on? That table is the Step Matrix — one of the three aggregated representations of trajectories described in Path Analysis.

Five paths merged into a trajectory tree, each node carrying the number of paths passing through it
Five example paths stacked into a trajectory tree: identical beginnings share a branch, and each node carries the number of paths passing through it.
The step matrix of those five paths: one row per event, one column per step
The same tree counted by step. The two cart nodes at step 3 — one reached via catalog, one via search — merge into a single cell: 2 + 1 = 3 of 5 paths.

Reading it:

  • A cell is a share of paths, not of events. Row cart, column 3 = 0.6 means 60% of all paths had cart as their third event.
  • Every column sums to 1 (in diff mode, to 0), because every path is somewhere at every step. Paths that have ended sit in path_end, which is why that row fills up towards the right.
  • Branches merge. Two groups of users reaching cart at step 3 by different routes land in the same cell. The matrix tells you what happens at each step, not which route got there.

Step Matrix and Step Sankey are two renderings of exactly the same numbers — they share one headless method. The matrix is easier for reading a single event across steps and for spotting rare events; the Sankey is easier for following volume.

Anchoring on an event

By default step 1 is each path's own first event. path_pattern re-anchors the matrix on an event instead: every path is shifted until that event sits in column 0, and the steps before it get negative numbers.

Five paths shifted so that each path's cart event sits in column zero, with negative column numbers before it
Five example paths under path_pattern="cart": every path shifted until its cart event sits in column 0. Paths that reach the anchor later stick out to the left; paths that never reach it drop out of the view.

Column −1 then answers "what leads into this event?" and column +1 "what follows it?" — questions the start-anchored view smears across many columns whenever the event happens at different steps for different users.

A pattern with several anchors ("add_to_cart->.*->purchase", where .* matches any run of events) draws one block of columns per anchor, side by side, so you can walk a funnel and still see each step's neighbourhood. When a block's edge isn't a real path boundary the widget draws it serrated, signalling that paths continue beyond the visible range.

Usage

stream.step_matrix(path_pattern="purchase")
stream.step_matrix(path_pattern="add_to_cart->.*->purchase")
stream.step_matrix(diff=("user_lifecycle", "new", "loyal"))

Examples

Basic

Without a path_pattern, the matrix is anchored at path_start: column 0 is the first step of every path, and each column to the right is one step further in.

stream.step_matrix()

Path pattern - central event

A single event as path_pattern re-centers the matrix on that event instead of path_start: column 0 is always purchase, negative columns are the steps leading up to it, positive columns are what follows.

stream.step_matrix(path_pattern="purchase")

Path pattern - funnel patterns

Chaining several anchors with .* renders one matrix block per anchor, side by side, so you can follow a multi-step funnel across blocks.

stream.step_matrix(path_pattern="payment_details->.*->shipping_details->.*->purchase", step_window=2)

Path pattern - drop-off points

path_pattern="path_end" centers on where paths end, so the columns to the left show what users tend to do right before dropping off (or completing their path).

stream.step_matrix(path_pattern="path_end")

Diff mode

Passing diff splits paths into two segments and shows the difference between them at each step, making it easy to spot where the segments' behavior diverges.

stream.step_matrix(diff=["platform", "mobile", "desktop"])

Parameters

Data

Data parameters change the computed result. They are exactly the arguments of the widget's headless twin stream.step_matrix_data() — see headless mode below.

ParameterTypeDescription
max_stepsint, default 10Number of path steps to compute on each side of the anchor.
difftuple or list, optionalDraws a comparative chart for a pair of segments; see Diff mode. (segment_col, value1, value2) or (path_ids1, path_ids2); value2 may be <REST>.
path_colstr, optionalPath ID column override; defaults to schema.path_col.
path_patternstr, optionalRestrict/split paths using a "->"-separated sequence of anchor events, where .* matches any run of events, e.g. "add_to_cart->.*->purchase". Without a pattern, shows the whole path from path_start to path_end. Multiple anchors render one matrix block per anchor, side by side. A pattern that doesn't start at path_start or end at path_end shows a serrated edge, signalling paths continue beyond the visible range. To see the neighborhood around a single event: path_pattern="add_to_cart".

Display

Display parameters only affect how the widget is rendered.

ParameterTypeDescription
step_windowint, default 3Number of step columns shown around each anchor.
heightint, default 600Widget height in pixels.
sidebar_openbool, default TrueWhether the sidebar starts open.
state_filestr, optionalJSON file the widget state is bound to; see Saving widget state.

Headless mode

stream.step_matrix_data()

Alias for step_sankey_data — Step Matrix and Step Sankey render the same underlying per-step data, so both widgets share one headless method.