Skip to main content

boxcox_capability

Function boxcox_capability 

Source
pub fn boxcox_capability(
    data: &[f64],
    usl: Option<f64>,
    lsl: Option<f64>,
    lambda_range: (f64, f64),
) -> Result<NonNormalCapabilityResult, NonNormalCapabilityError>
Expand description

Compute process capability indices for non-normal data via Box-Cox transformation.

The data are first transformed to approximate normality using the optimal Box-Cox parameter λ, estimated via maximum likelihood over lambda_range (usually DEFAULT_LAMBDA_RANGE). Specification limits are transformed using the same λ. The long-term capability indices (Pp, Ppk, Ppu, Ppl) are then computed on the transformed scale. The short-term indices (Cp, Cpk, Cpu, Cpl) are not reported — see NonNormalCapabilityResult::indices for why.

Specification limits are optional: without either, λ and NonNormalCapabilityResult::lambda_at_bound are still estimated and indices is None — the “does a transform achieve normality” half of a non-normal capability workflow comes before the limits are known.

§Arguments

  • data — Process observations. All values must be strictly positive.
  • usl — Upper specification limit (optional). Must be positive if provided.
  • lsl — Lower specification limit (optional). Must be positive if provided.
  • lambda_range — (min, max) λ search range, finite with min < max.

§Errors

Returns NonNormalCapabilityError if:

  • Fewer than 4 data points are provided.
  • Any data value is ≤ 0 (Box-Cox requires strictly positive data).
  • lambda_range is not finite with min < max.
  • A specification limit is ≤ 0 (cannot be Box-Cox transformed).
  • Capability computation fails (e.g., zero variance in transformed data).

§Examples

use u_analytics::capability::{boxcox_capability, DEFAULT_LAMBDA_RANGE};

// Right-skewed data
let data: Vec<f64> = (1..=20).map(|i| (i as f64 * 0.3_f64).exp()).collect();
let result = boxcox_capability(&data, Some(100.0), Some(1.0), DEFAULT_LAMBDA_RANGE).unwrap();
assert!(!result.lambda_at_bound);
assert!(result.indices.expect("limits given").ppk.is_some());

// No limits yet: the transform alone.
let lambda_only = boxcox_capability(&data, None, None, DEFAULT_LAMBDA_RANGE).unwrap();
assert_eq!(lambda_only.lambda, result.lambda);
assert!(lambda_only.indices.is_none());