Skip to content

SequenceData()

After you have prepared your sequence dataset through preprocessing functions (or if your data are already clean, you may skip this step), the next stage is to formally define the sequence data structure. In other words, SequenceData is the canonical entry point for representing sequences in Sequenzo.

You might ask: why is this step necessary? Think of it as similar to how pandas (a Python package for data analysis) uses a DataFrame: before you can analyze tabular data efficiently, you first need a consistent container that standardizes how rows, columns, and metadata are stored.

In the same way, SequenceData() creates a dedicated data structure for representing sequences in social sequence analysis.

By doing so, it ensures that your sequences are stored in a unified format with:

  • consistent state definitions and ordering,
  • reproducible numeric encoding and color mapping,
  • built-in methods to summarize, validate, and visualize the dataset.

This formal definition is what allows all subsequent steps, such as distance computation, clustering, and visualization, to work reliably across different datasets and projects.

Typical Workflow

  1. Ensure your table has one row per entity (e.g., individual / firm / region / organization) and one column per time point. Example input DataFrame:
Entity IDY1Y2Y3Y4
1EDUEDUFTFT
2EDUUNEMPUNEMPFT
3FTFTFTFT

Each row represents an individual (a sequence), and each column represents a time point.

Note:

It is recommended to clean column names during preprocessing so that time points are pure numbers (1, 2, 3, 4) instead of Y1–Y4. Otherwise, in visualizations where the x-axis represents time, labels like Y1, Y2, Y3, Y4 will appear, which may look less clean and less intuitive than 1–4. For further instruction on how to clean your time columns in the dataframe, please refer to Clean time columns

  1. Provide the full, ordered list of states in the exact order you want them to appear in encodings and legends (e.g., 'Low', 'Medium', 'High', not shuffled).
  2. Optionally provide an ID column for stable indexing and clustering.
  3. Initialize SequenceData, then use values / to_numeric() for downstream algorithms or get_legend() / get_colormap() for plotting.

Function Usage

A minimal example with only the required parameters (sufficient for most use cases):

python
sequence = SequenceData(
    data=df,
    time=['1','2','3', ...],        # ordered time columns
    states=['EDU','FT','UNEMP'],    # full, ordered state space
    labels=['Education','Full-time','Unemployed'],  # optional display labels; the order must correspond one-to-one with states; if labels are not set, legends will fall back to the state names
    id_col='Entity ID',             # ID column; if missing, create one with assign_unique_ids
)

A complete example with all available parameters (for advanced customization):

python
sequence = SequenceData(
    data=df,
    time=['1','2','3', ...],        # ordered time columns
    states=['EDU','FT','UNEMP'],    # full, ordered state space
    labels=['Education','Full-time','Unemployed'],  # optional display labels; the order must correspond one-to-one with states; if labels are not set, legends will fall back to the state names
    id_col='Entity ID',             # ID column; if missing, create one with assign_unique_ids
    weights=None,                   # optional (defaults to 1 per row)
    start=1,                        # start index used in summaries
    custom_colors=None,             # optional list of colors
    additional_colors=None,         # optional dict to assign custom colors to specific states, e.g. {"Other": "#BDBDBD"}
    missing_values=None,            # optional custom missing indicators, e.g. [99, "N/A"]
    void="%",                       # symbol for positions outside the observation window
    alpha=1.0                       # opacity for colors (0–1)
)

Entry Parameters

ParameterRequiredTypeDescription
dataDataFrameInput dataset with rows = entities, cols = time points.
timelistOrdered list of time column names.
stateslistOrdered state space. Controls encoding & colors.
labelslistHuman-readable names, same length as states.
id_colstrColumn name for unique sequence IDs. If omitted, data.index is used. If your data lacks an ID column, create one with assign_unique_ids. Recommended for stable IDs in clustering output.
weightsndarrayRow weights. Default = all ones.
startintStarting index in summaries. Default = 1.
custom_colorslistUser-specified color list. Must match the final state count, or the non-missing state count when Sequenzo auto-adds Missing.
additional_colorsdictAssign custom colors to specific states, e.g. {"Other": "#BDBDBD"}. Cannot be used with custom_colors.
missing_valuesint/float/str/listCustom missing value indicators. Default: auto-detect (NaN, "Missing", "NaN"). Examples: 99, [99, "N/A"].
voidstr or NoneSymbol for positions outside the observation window, following TraMineR's seqdef convention. Default = "%". Void marks time points before entry or after exit; it is a different concept from missing values, which are unknown states inside the window.
alphafloatOpacity for all state colors (0–1). Default = 1.0.

Note

  1. Instead of slicing arrays to indirectly construct the time list (e.g., time=list(df.columns)[1:]), we recommend explicitly specifying it (e.g., time=[str(y) for y in range(1800, 2023)]). This makes the intended time span unambiguous and prevents indexing errors.

  2. Summaries refers to the dataset overview produced after initializing SequenceData, typically through describe() and related methods. These summaries include state distributions, missing-value information, and sequence length. The start parameter controls the first time index shown there, for example starting at 1 rather than 0.

Returns

A SequenceData instance: the standardized sequence object that downstream functions consume. Its most-used attributes are values (encoded sequence array), ids (entity identifiers), states and labels (the alphabet and display names), and weights. Methods such as describe(), to_numeric(), get_legend(), and get_colormap() are documented below.

Key rules to remember

1. Order is everything

Colors follow the order of states you pass in. If states = [1, 2, 3], the first color maps to state 1, the second to 2, etc. Keep the same states order across your whole project to keep colors consistent.

2. Labels must be strings

Labels are used in legends. If you pass non-string labels, Sequenzo will raise a TypeError.

3. Missing values get a fixed light gray by default

If your data contain missing cells and you didn’t include a dedicated “Missing” state, SequenceData will auto-add "Missing" into the list of states, and color it light gray (with the color code #cfcccc).

If you provide custom_colors with one fewer entry than the final number of states (i.e., you only colored the non-missing states), the class will append the gray for you automatically.

4. Length checks

If you provide the custom_colors parameter, its length must match either:

  • the total number of states (including "Missing" if you included it yourself), or
  • the number of non-missing states (SequenceData will then append gray for Missing).

5. A long list of states

By default, ≤20 states use a Spectral palette (reversed for better readability), 21-40 states use viridis, and >40 states use a combined palette (viridis + Set3 + tab20). You can override any of these by supplying custom_colors.

For further details about coloring, please refer to this documentation.

Key Features

Validation

  • Ensures all non-missing data values are included in states; extra states are allowed for stable ordering across subsets.
  • Confirms id_col uniqueness (if provided).
  • Checks labels length and type.
  • Validates weights length; defaults to 1 if omitted.

Missing Values

  • Auto-detects pandas NaN and string "Missing" or "NaN" (case-insensitive).
  • Use missing_values to specify custom indicators (e.g., 99, [99, 9, "N/A"]).
  • If your states list doesn’t include "Missing" but the data contains missing values, Sequenzo will auto-add "Missing" so those cells are clearly labeled as missing.
  • Maps missing cells to the last integer code.
  • Recommendation: explicitly include "Missing" in your states and labels.

Encoding & Colors

  • States are mapped in user-provided order → integer codes 1...N (where N is the total number of states).

  • This order controls:

    • integer encoding
    • colormap assignment
    • legend order

Color Management

  • If custom_colors is given, its length must match the final state count, or the non-missing state count when Sequenzo auto-adds "Missing". Entries can be hex color codes (e.g., #BD462D) or RGB tuples.
  • Use additional_colors to assign custom colors to specific states while keeping the default palette for others (e.g., additional_colors={"Other": "#BDBDBD"}). Cannot be combined with custom_colors.
  • Otherwise, the default palette is: "Spectral" (≤20 states), "viridis" (21–40 states), or a combined palette (viridis + Set3 + tab20 for >40 states).
  • Colors are reversed by default for contrast.

Core Attributes

  • seq.states, seq.labels → canonical state space.
  • seq.ids → entity IDs.
  • seq.n_sequences → number of sequences.
  • seq.n_steps → sequence length.
  • seq.weights → row weights (NumPy array).

Key Methods

MethodReturnsDescription
get_colormap()ListedColormapColormap aligned to codes 1...N.
get_legend()(handles, labels)Prebuilt legend for plotting.
describe()printDataset summary with missing overview and weights.
plot_legend()NoneDisplays or saves the state legend, with vertical or horizontal layout.
to_numeric()ndarrayInteger-coded sequence data as NumPy array.
to_dataframe()DataFrameProcessed sequence dataset.
show_color_palette()dictPreview default colors for this instance's states.
show_default_color_palette(n_states, ...)dictStatic: preview colors for given number of states.

Note We list key attributes and key methods here, but you’ll rarely need to call them directly. After you initialize SequenceData(), a dataset summary is printed automatically. These are mainly for:

  1. inspecting details (e.g., missingness, encodings, weights);
  2. plotting utilities (e.g., get_legend() / get_colormap());
  3. exporting data for downstream algorithms via to_numeric() / to_dataframe().

Standalone Legend

plot_legend() now supports two layouts:

python
# Compact vertical legend with the title "States"
sequence_data.plot_legend()

# Horizontal legend matching grouped index plots
sequence_data.plot_legend(style="horizontal")

Available options:

ParameterDescription
style"vertical" (default) or "horizontal".
ncolNumber of columns for the horizontal legend. If omitted, Sequenzo chooses a readable layout and avoids an awkward final row with only one or two labels.
fontsizeLegend font size. Default is 10.
show_borderWhether to draw a legend frame. Defaults to True for vertical legends and False for horizontal legends.
save_as, dpiOptional output path and resolution.

Examples

1. Minimal Construction (with missing values)

python
# Create a SequenceData object

# Define the time-span variable
time_list = list(df.columns)[1:]

# We choose to use 'D1 (Very Low)', 'D10 (Very High)' as the states for readability and interpretation.
# states = ['Very Low', 'Low', 'Middle', 'High', 'Very High']
states = ['D1 (Very Low)', 'D10 (Very High)', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9']

sequence_data = SequenceData(df,
                             time=time_list,
                             id_col="country",
                             states=states,
                             labels=states)

sequence_data

Output:

text
[!] Detected missing values (empty cells) in the sequence data.
    → Automatically added 'Missing' to `states` and `labels` for compatibility.
    However, it's strongly recommended to manually include it when defining `states` and `labels`.
    For example:

        states = ['At Home', 'Left Home', 'Missing']
        labels = ['At Home', 'Left Home', 'Missing']

    This ensures consistent color mapping and avoids unexpected visualization errors.

[>] SequenceData initialized successfully! Here's a summary:
[>] Number of sequences: 194
[>] Number of time points: 223
[>] Min/Max sequence length: 216 / 223
[>] There are 7 missing values across 1 sequences.
    First few missing sequence IDs: ['Panama'] ...
[>] Top sequences with the most missing time points:
    (Each row shows a sequence ID and its number of missing values)

             Missing Count
Sequence ID
Panama                   7
[>] States: ['D1 (Very Low)', 'D10 (Very High)', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'Missing']
[>] Labels: ['D1 (Very Low)', 'D10 (Very High)', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'Missing']
SequenceData(194 sequences, States: ['D1 (Very Low)', 'D10 (Very High)', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'Missing'])

2. Add IDs If Missing

python
from sequenzo import assign_unique_ids
df = assign_unique_ids(df, id_col_name='Entity ID')

sequence = SequenceData(
    df,
    time=year_cols,
    states=states,
    id_col='Entity ID'
)

Authors

Code: Yuqi Liang

Documentation: Yuqi Liang

Edited by: Yuqi Liang, Yukun Ming, Liangxingyun He

See Also

Sequenzo is released under the BSD-3-Clause License; this documentation site source is licensed under MIT.