Skip to content

Unpivot

Transform

Reshape wide tables into long format. Selected columns are melted into two new columns: one holding the original column name, one holding its value. Each input row produces one output row per unpivoted column. Use it to convert spreadsheet-style monthly columns into a single date column, or to feed wide pivot tables into transforms that expect tidy data.

Unpivot is a full-dataset batch transform: it buffers the entire input before producing output, because it needs the row shape to determine which columns are index columns (everything not unpivoted) versus value columns (the ones being melted).

For an input row with N unpivoted columns, the transform emits N output rows. Each output row carries:

  • All non-unpivoted columns from the source row, unchanged (the “index” columns)
  • The variable column, set to the name of one of the unpivoted columns
  • The value column, set to the cell value at that column (or null if missing)

The order of output rows is: input row 1’s first unpivoted column, then input row 1’s second, …, then input row 2’s first, and so on. The order of variables within a group follows the order of columnsToUnpivot in the configuration, not the column order of the source.

If columnsToUnpivot is empty, rows pass through unchanged.

Input: One tabular data connection. Output: A long-format table with all index columns plus the variable and value columns.

OptionTypeDefaultDescription
columnsToUnpivotstring[][]Names of columns to melt. Empty list is a passthrough.
variableColumnNamestring"variable"Name of the output column that holds the original column name. Required.
valueColumnNamestring"value"Name of the output column that holds the cell value. Required.

You have quarterly sales as wide columns (q1, q2, q3, q4) and want them as one quarter / sales pair per row.

Before:

customerq1q2q3q4
Acme Corp1200150018002100
Beta Inc80090011001300

Configuration: columns to unpivot: ["q1", "q2", "q3", "q4"], variable column: quarter, value column: sales.

After:

customerquartersales
Acme Corpq11200
Acme Corpq21500
Acme Corpq31800
Acme Corpq42100
Beta Incq1800
Beta Incq2900
Beta Incq31100
Beta Incq41300

Multiple index columns are preserved per output row

Section titled “Multiple index columns are preserved per output row”

You want to melt scores while keeping both student and class as identifiers.

Before:

studentclassmathenglishscience
Alice5A928895
Bob5B788480

Configuration: columns to unpivot: ["math", "english", "science"], variable column: subject, value column: score.

After:

studentclasssubjectscore
Alice5Amath92
Alice5Aenglish88
Alice5Ascience95
Bob5Bmath78
Bob5Benglish84
Bob5Bscience80
  • Index columns are inferred from the first row, not from the schema. The transform takes Object.keys(rows[0]) and treats every key not in columnsToUnpivot as an index column. If row 1 is missing a key that later rows have, that key is dropped from the output. To avoid surprises on ragged inputs, run Stack Rows in union mode upstream so every row has the same shape. See apps/web/src/transforms/unpivot/logic.ts:72-74.
  • Missing values become null, not empty string. When an unpivoted column is absent from a row (or its value is undefined), the output value cell is null. Empty string in the source is preserved as "". See apps/web/src/transforms/unpivot/logic.ts:84.
  • One input row produces N output rows in a deterministic order. The output groups together one input row’s unpivoted columns before moving on to the next input row. Sort downstream if you need a different order — Unpivot does not interleave rows by variable.
  • Pivot — the inverse: roll long-format data back into wide columns.
  • Group By — aggregate the unpivoted long format (e.g. sum sales per quarter across all customers).
  • Filter Rows — drop specific variables (e.g. keep only q4 rows) after unpivoting.