Skip to content
Development documentation. The PyPI package predates these APIs. Install from GitHub instead: pip install 'increment @ git+https://github.com/kylejcaron/increment.git' Keep any extras requested by the guide, such as increment[dashboard].

Segment analysis and rollout

segment_heterogeneity(estimates, alpha, tau_prior_scale)

Cochran’s Q, tau^2, I^2, an HKSJ pooled effect, and tau-marginalised per-segment shrinkage, over every declared segment for each (metric, method, group_id, dimension, source, estimand, value_scale) grouping key in estimates.

estimates must come from a SINGLE run_breakout call - a standalone call stamps source=None, so two independent calls on the same dimension would silently merge into one Q.

A key needs at least 2 live segments on a scale to run a test; absolute encouragement rows use their persisted additive moments for the absolute scale, while rows without usable moments are dropped from that scale only. A segment unusable on ONE scale only is dropped from that scale’s math (excluded="zero_variance") and tested normally on the other. A degenerate HKSJ pooled variance falls back to the wider plug-in interval for that row only. Only when posterior integration cannot be resolved within the numerical budget are that scale’s shrunken rows withheld (excluded="estimation_failed", with a breakout.heterogeneity.posterior_integration_unresolved warning carrying the failure’s context); the raw rows are unaffected.

The relative-scale raw row reuses BreakoutEstimate.lift verbatim when no rebuild is needed; Q/tau^2/pooled/shrunken use the raw pre-update lift.log_mean/lift.log_se (see :func:_relative_raw_lift). A row whose stored interval was set by a BH/FCR family-selection correction is withheld instead of rebuilt (excluded="reference_not_normal", lift=None) only when the requested alpha differs from that row’s own corrected alpha — rebuilding it at a different, uncorrected alpha would silently re-narrow or widen it back to nominal coverage. A matching-alpha family-corrected row needs no such withhold and reuses its stored interval verbatim instead.

Absolute-primary raw rows likewise preserve their stored intervals at a matching alpha. Allowed rebuilds use the primary sampling reference, not a relative row’s additive-sidecar reference.

estimates : BreakoutEstimates A single run_breakout call’s dense output. alpha : float Two-sided significance level, shared by every interval. tau_prior_scale : float HalfNormal prior scale on tau for the tau-marginalised shrinkage, forwarded to :func:~increment.estimation.meta. marginalized_segment_intervals. The default (0.30) is calibrated for the log-RR (relative) scale; an absolute-scale metric whose true between-segment tau is not of that order (e.g. a dollar metric) over-shrinks under the default with no warning — pass a scale matching that metric’s own units. Raises

Section titled “estimates : BreakoutEstimates A single run_breakout call’s dense output. alpha : float Two-sided significance level, shared by every interval. tau_prior_scale : float HalfNormal prior scale on tau for the tau-marginalised shrinkage, forwarded to :func:~increment.estimation.meta. marginalized_segment_intervals. The default (0.30) is calibrated for the log-RR (relative) scale; an absolute-scale metric whose true between-segment tau is not of that order (e.g. a dollar metric) over-shrinks under the default with no warning — pass a scale matching that metric’s own units. Raises”

ValueError Propagated from cochran_q/hksj_pooled_mean on malformed moment inputs; also raised when a live row’s stored relative-scale interval must be rebuilt at alpha but the rebuild would misrepresent it (wrong shape or reference distribution — see :func:_relative_raw_lift). A row corrected by a BH/FCR family-selection pass is withheld instead of raising when its own corrected alpha differs from the requested one (see above). Returns

Section titled “ValueError Propagated from cochran_q/hksj_pooled_mean on malformed moment inputs; also raised when a live row’s stored relative-scale interval must be rebuilt at alpha but the rebuild would misrepresent it (wrong shape or reference distribution — see :func:_relative_raw_lift). A row corrected by a BH/FCR family-selection pass is withheld instead of raising when its own corrected alpha differs from the requested one (see above). Returns”

SegmentHeterogeneityResult (summary, segments) - see :class:HeterogeneitySummary and :class:SegmentEstimate.

segment_contrast(estimates, dimension_value_a, dimension_value_b, alpha)

Contrast segment dimension_value_a’s lift against dimension_value_b’s.

estimates must already be scoped to ONE (metric, method, group_id, dimension, source, estimand, value_scale) combination - exactly two rows, one per label - or this raises rather than guessing which pair to contrast.

Relative rows (value_scale="relative") return a value on the same back-transformed scale as :func:increment.power.core.segment_pairwise_required_sample_size’s contrast: value = exp(delta) - 1 where delta = log1p(r_A) - log1p(r_B). Absolute rows (value_scale="absolute", e.g. an encouragement LATE) return the plain additive difference value_A - value_B with no log transform - log1p is undefined at or below an additive effect of -1, which a valid absolute effect routinely is.

Segments partition a breakout’s rows with independent control arms and CUPED thetas, so the contrast variance is the plain sum var_a + var_b.

Running this on every one of a dimension’s pairs without correction re-introduces the multiple-comparisons problem it exists to avoid for one pre-specified pair; use :func:increment.estimation.meta. cochran_q’s joint test when scanning every pair.

ValueError Not exactly one row per label, the two rows come from different groupings, either is missing an interval, or either carries a reference this rebuild cannot invert: non-fixed-horizon inference (a sequential width is not a critical value times a standard error) or a t sampling reference (built with a t critical value, not a Normal one). Exact-binomial rows are also refused because their confidence sets do not encode a Normal variance; rerun the breakout with a fixed-horizon Normal-reference method, such as CUPED with valid covariate moments, before contrasting those segments. A directional (open) row IS accepted: its single calibrated bound recovers the variance at the row’s own full allocated tail (Estimate.open_side); an unavailable row (both bounds None) is not.

Every value below is unweighted: each usable segment contributes equally, regardless of the exposure it carries. An exposure-weighted policy value was measured before this shipped and deliberately left out — under weighting the winner’s-curse correction could not meet the accuracy bar the unweighted correction is adopted against, and a weighted headline whose selection bias cannot be removed honestly is worse than none.

segment_rollout_recommendation(estimates, metrics, rollout_cost, tau_prior_scale)

Recommend which segments to roll out, and price the rollout, for each (metric, method, group_id, dimension, source, estimand, value_scale) grouping key found in estimates.

estimates must come from a SINGLE run_breakout call - a standalone call stamps source=None, so independent calls on one dimension would silently merge into a single selection problem.

Cost resolution, highest precedence first: an explicit rollout_cost argument (a mapping’s unknown name is REFUSED); then the metric’s own declared rollout_cost; then 0.0.

Only RELATIVE moments are read; see the module docstring. A key needs at least 2 usable segments; fewer are silently skipped — so an encouragement breakout’s LATE rows (additive lift, no log-scale moments) form their own key and emit nothing, rather than counting against the ITT key’s exclusions. A segment with unusable statistics is dropped, reported excluded="zero_variance", selected=None. Values are UNWEIGHTED by exposure - read :class:RolloutRecommendation before quoting one. Parameters

Section titled “Only RELATIVE moments are read; see the module docstring. A key needs at least 2 usable segments; fewer are silently skipped — so an encouragement breakout’s LATE rows (additive lift, no log-scale moments) form their own key and emit nothing, rather than counting against the ITT key’s exclusions. A segment with unusable statistics is dropped, reported excluded="zero_variance", selected=None. Values are UNWEIGHTED by exposure - read :class:RolloutRecommendation before quoting one. Parameters”

estimates : BreakoutEstimates A single run_breakout call’s dense output. metrics : Sequence[Metric], optional Metric declarations, read only for rollout_cost. rollout_cost : float or Mapping[str, float], optional Explicit break-even override(s), as relative lift. tau_prior_scale : float HalfNormal prior scale on tau, forwarded to :func:~increment.estimation.rollout.segment_rollout. Raises

Section titled “estimates : BreakoutEstimates A single run_breakout call’s dense output. metrics : Sequence[Metric], optional Metric declarations, read only for rollout_cost. rollout_cost : float or Mapping[str, float], optional Explicit break-even override(s), as relative lift. tau_prior_scale : float HalfNormal prior scale on tau, forwarded to :func:~increment.estimation.rollout.segment_rollout. Raises”

ValueError An explicit rollout_cost key naming no known metric, a non-finite / <= -1 cost, or the estimator’s own guards — including estimation.meta.posterior_integration_unresolved, propagated unchanged when a key’s tau posterior cannot be integrated within the numerical budget: a recommendation row has no field to carry that reason, and "refuse" means the offset guard fired, so the failure is never reported as one. Returns

Section titled “ValueError An explicit rollout_cost key naming no known metric, a non-finite / <= -1 cost, or the estimator’s own guards — including estimation.meta.posterior_integration_unresolved, propagated unchanged when a key’s tau posterior cannot be integrated within the numerical budget: a recommendation row has no field to carry that reason, and "refuse" means the offset guard fired, so the failure is never reported as one. Returns”

SegmentRolloutResult (recommendations, segments) - see :class:RolloutRecommendation and :class:RolloutSegment.