Iterating With Previous And Cycles

作者 gopigment6fec49f4ce9d无许可证22 个星标收录于 2026年10月8日更新于 2026年10月8日仓库2天前更新

Execution skill. Use when writing PREVIOUS, PREVIOUSOF, or PREVIOUSBASE formulas, configuring iterative calculation cycles, or debugging circular dependency errors.

AI 生成的概览

指导编写 Pigment 的 PREVIOUS 与 PREVIOUSOF 公式、配置迭代计算循环并排查循环依赖错误。

功能
该技能仅包含说明,讲解在 Pigment 中如何在 PREVIOUS、PREVIOUSOF 与 FILLFORWARD 之间选择以进行迭代计算,包括语法、常见错误和 IFBLANK 陷阱。它描述了使用循环工具创建和更新迭代计算循环的编程工作流,以及指标数量和维度大小等约束。它还涵盖组合基础公式错误的排查、缩减启发式,以及带有预期加速效果的性能优化策略。
适用场景
适用于编写 PREVIOUS、PREVIOUSOF 或 PREVIOUSBASE 公式、配置迭代计算循环,或在 Pigment 模型中排查循环依赖错误时。它也适用于优化余额滚动、库存或贷款摊销模式的性能。
运行要求
不包含脚本,仅为说明。它假定可以访问 Pigment 及其循环工具(list_cycles、create_cycle、update_cycle)以执行编程式循环工作流。

Iterating with PREVIOUS and Cycles

Iterative calculations let a metric reference its own previous value along a dimension (typically time). Use them only for true metric-level circular dependencies; Pigment does not support cell-level circulars like Excel.

Choose the Right Iterative Tool

ScopeFunctionWhen to use
Single blockPREVIOUS(Dimension [, Offset])All circular-referencing formulas are in one block
Multiple blocksPREVIOUSOF(Metric)Circular references span different blocks; requires an iterative calculation cycle

Rule: loop within a single metric with PREVIOUS; loop across multiple metrics with PREVIOUSOF. PREVIOUSBASE is deprecated; use PREVIOUSOF instead.

Write PREVIOUS Formulas

Syntax: PREVIOUS(IteratingDimension [, Offset])

The argument is the iterating dimension, not the metric. Offset defaults to 1; can be a positive integer or an Integer metric on the same dimensions.

Common error: PREVIOUS('My Metric Name') fails with Unknown List: My Metric Name. The fix: use PREVIOUS(Month) — the dimension, not the metric name.

pigment
// Cash balance roll-forward (single metric)Cash = PREVIOUS(Month) + Income - Expense

Use PREVIOUS only when the entire roll-forward lives in one metric. When Beginning and Ending are separate metrics, use PREVIOUSOF and a cycle (see below).

The engine computes the entire formula (including everything before and after PREVIOUS) before moving to the next cell. Post-processing (filtering) should happen in a separate metric.

Avoid the IFBLANK + PREVIOUS Pitfall

pigment
// BAD — returns blanks everywhere including where the filter is TRUEIFBLANK('Source', PREVIOUS(Month))['Filter Boolean']

Why: for earlier items where the filter is FALSE, the engine emits blanks. When TRUE, PREVIOUS points to a blank cell, propagating BLANK forward.

Fix: separate the PREVIOUS expression from the filter:

pigment
// Metric 1 — 'Filled Source'IFBLANK('Source', PREVIOUS(Month))
// Metric 2 — 'Filtered Result''Filled Source'['Filter Boolean']

Set Up PREVIOUSOF Cycles

Before using PREVIOUSOF, create an iterative calculation cycle listing all participating metrics and the iterating dimension. PREVIOUSOF will not resolve without a cycle. Do not rewrite to PREVIOUS on itself; this changes the mathematical meaning.

Programmatic workflow

  1. Call tool:list_cycles to check if a cycle already exists.
  2. Identify all metrics in the dependency chain and the iteration dimension (typically Month).
  3. Create all participating metrics first (they must exist before being added to the cycle).
  4. Call tool:create_cycle with cycleName, iterativeDimensionId, and all metricIds.
  5. Only after the cycle is created, write PREVIOUSOF formulas. Writing PREVIOUSOF before creating the cycle produces errors.
  6. Use tool:update_cycle to add or remove metrics from an existing cycle.
  7. Verify all mutually dependent metrics participate.

Constraints

  • Maximum ~10 metrics per cycle (verify the current platform limit)
  • All metrics must include the iteration dimension in their structure
  • Iteration dimension must have fewer than 10,000 items
  • Cannot combine or link two cycles together

Standard balance pattern

Use this when beginning and ending balances are separate metrics (inventory, cash, loan balances). Create the cycle first, then write PREVIOUSOF formulas.

pigment
// Beginning balance — after cycle existsIFDEFINED(PREVIOUSOF('Ending Balance'), PREVIOUSOF('Ending Balance'), 'Opening Balance')
// Ending balance — inflows and outflows may be direct references or intermediate metrics'Beginning Balance' - 'Outflows' + 'Inflows'

Do not substitute 'Ending Balance'[SELECT: Month - 1] for PREVIOUSOF; it does not participate in the cycle and breaks cross-metric roll-forwards.

Cash Balance from Sparse Revenue

pigment
// Seed with 0 when no prior period exists; add net income each monthIFDEFINED(PREVIOUS(Month), PREVIOUS(Month), 0) + IFDEFINED('Net Income', 'Net Income', 0)

Use IFDEFINED to handle the first period (no prior balance) and months with no data.

Apply the Reduction Heuristic (performance only)

Before collapsing a PREVIOUSOF cycle into PREVIOUS, confirm that separate Beginning/Ending metrics are not required. Many planning models expose both metrics for reporting, reorder logic, or drill-down views; in those cases keep the two-metric PREVIOUSOF + cycle pattern even if the math could collapse.

Only collapse when all of the following are true:

  1. The user needs only one balance metric (no separate Beginning metric in outputs).
  2. No other metric in the chain independently references a prior value.
  3. You have verified the collapsed formula is equivalent after substitution.
pigment
// Collapsed version (single metric only — often more performant)'Ending Balance' = PREVIOUS(Month) + 'Movements'

When in doubt, prefer PREVIOUSOF + cycle. Collapsing changes which metrics exist in the model and is harder to extend later.

Debug Iterative Formula Errors

When a cycle is active, Pigment builds a combined base formula. Three individually valid formulas can combine into an invalid base formula.

Key rule: modifiers (BY, SELECT, REMOVE, FILTER) are supported as long as they do not reference the iterating dimension. Window functions (CUMULATE, MOVINGAVERAGE, MOVINGSUM) are supported within cycle metrics.

pigment
// BAD — REMOVE on the iterating dimension inside a cycle metric'Incoming' = 'Beginning'[REMOVE: Month]

Error: "A dimension modifier using the iterating dimension Month can't be applied to a metric in the iterative calculation."

Use FILLFORWARD Instead When Possible

FILLFORWARD is non-iterative and much faster. Use it when you only need to carry the last known value forward with no calculation at each step.

pigment
// BAD — iterative carry-forwardIFBLANK('Status Input', PREVIOUSOF('Current Status'))
// GOOD — non-iterative, 10-50x fasterFILLFORWARD('Status Input', Month)

Use PREVIOUS/PREVIOUSOF only when each step involves a computation (balance + inflows - outflows, conditional reorder logic, etc.).

Optimize Iterative Calculation Performance

Iterative calculations are inherently sequential (period N depends on 1..N-1). Cost drivers:

  • Iterating dimension length: More items = more sequential steps
  • Number of other dimensions: More dimensions = more iteration chains
  • Data density: Dense data = more cells per step
  • Formula complexity: Heavy sub-expressions multiply cost per step

Optimization strategies (ordered by typical impact)

  1. Subset the iterating dimension to relevant periods (current fiscal year, rolling 90 days). 5-20x faster.
  2. Use FILLFORWARD for simple carry-forward logic. 10-50x faster.
  3. Aggregate before iterating (REMOVE unnecessary dimensions before the iterative metric). 10-1000x faster.
  4. Pre-compute starting points so the engine does not roll forward from the beginning of time.
  5. Consider coarser granularity: monthly instead of daily (~30x fewer iterations).
  6. Keep sub-expressions light: avoid densifying functions like ISBLANK inside PREVIOUS. Prefer IFDEFINED(M, M, PREVIOUS(Month)) over IF(ISBLANK(M), PREVIOUS(Month), M).
  7. Minimize PREVIOUS calls: PREVIOUS(Month) * (A + B) is faster than PREVIOUS(Month) * A + PREVIOUS(Month) * B.
  8. Eliminate unused metrics from cycle configurations: only include metrics in the actual dependency chain.

Performance expectations

GranularityPeriods/year5-year horizon
Monthly1260 (fast)
Weekly52260 (moderate)
Daily3651,825 (slow)

When Iterative Calculations Are Unavoidable

Some patterns require iteration:

  • Balance roll-forwards with conditional logic (credit line draws, reorder points)
  • Inventory with inflows/outflows where each period depends on the prior ending balance
  • Loan amortization schedules

Optimize what you can (subsetting, dimensionality, granularity) and accept the remaining performance cost.

来源与署名

来源:gopigment/ai-plugins位于skills/iterating-with-previous-and-cycles提交6fec49f

许可证: 无许可证

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架