Anofox Statistics Extension - API Reference

March 27, 2026 · View on GitHub

Version: 0.6.0 DuckDB Version: 1.5.1+ Backend: Rust (anofox-regression 0.5.2, anofox-statistics 0.4.0, faer)

Overview

The Anofox Statistics Extension provides comprehensive regression analysis capabilities for DuckDB. Built with Rust for performance and reliability, it supports multiple regression methods including linear models, generalized linear models (GLM), augmented linear models (ALM), and constrained optimization (BLS/NNLS).

Quick Reference

Regression Methods

MethodScalarAggregateDocumentation
OLSols_fitols_fit_aggOLS
Ridgeridge_fitridge_fit_aggRidge
Elastic Netelasticnet_fitelasticnet_fit_aggElastic Net
WLSwls_fitwls_fit_aggWLS
RLSrls_fitrls_fit_aggRLS
BLS-bls_fit_aggBLS/NNLS
NNLS-nnls_fit_aggBLS/NNLS
PLSpls_fitpls_fit_aggPLS
Isotonicisotonic_fitisotonic_fit_aggIsotonic
Quantilequantile_fitquantile_fit_aggQuantile

GLM Functions

MethodAggregateDocumentation
Poissonpoisson_fit_aggPoisson
ALMalm_fit_aggALM

Statistical Hypothesis Tests

CategoryFunctionDocumentation
Parametrict_test_agg, one_way_anova_aggHypothesis Tests
Nonparametricmann_whitney_u_agg, kruskal_wallis_aggHypothesis Tests
Normalityshapiro_wilk_agg, jarque_bera_aggHypothesis Tests
Equivalencetost_t_test_agg, tost_paired_aggHypothesis Tests

Correlation Tests

FunctionDescriptionDocumentation
pearson_aggPearson correlationCorrelation
spearman_aggSpearman rank correlationCorrelation
kendall_aggKendall tau correlationCorrelation
distance_cor_aggDistance correlationCorrelation
icc_aggIntraclass correlationCorrelation

Categorical Tests

FunctionDescriptionDocumentation
chisq_test_aggChi-square independenceCategorical
fisher_exact_aggFisher's exact testCategorical
mcnemar_aggMcNemar's testCategorical
cramers_v_aggCramér's VCategorical
cohen_kappa_aggCohen's kappaCategorical

Diagnostics & Utilities

FunctionDescriptionDocumentation
vif, vif_aggVariance Inflation FactorDiagnostics
aic, bicModel selection criteriaDiagnostics
residuals_diagnostics_aggResidual analysisDiagnostics
aid_agg, aid_anomaly_aggDemand classificationAID

Table Macros

MacroDescriptionDocumentation
ols_fit_predict_byPer-group OLS predictionsTable Macros
ridge_fit_predict_byPer-group Ridge predictionsTable Macros
elasticnet_fit_predict_byPer-group Elastic NetTable Macros
wls_fit_predict_byPer-group WLSTable Macros
rls_fit_predict_byPer-group RLSTable Macros
bls_fit_predict_byPer-group BLSTable Macros
alm_fit_predict_byPer-group ALMTable Macros
poisson_fit_predict_byPer-group PoissonTable Macros
aid_anomaly_byGrouped anomaly detectionTable Macros

Deprecation Notice: The old *_predict_agg names (ols_predict_agg, etc.) are deprecated but still work for backwards compatibility. Use *_fit_predict_agg instead.


Function Types

Scalar Functions (Array-based)

Process complete arrays of data in a single call. Best for batch operations.

SELECT ols_fit(y_array, x_arrays);

Aggregate Functions (Streaming)

Accumulate data row-by-row. Support GROUP BY and window functions via OVER.

SELECT ols_fit_agg(y, [x1, x2]) FROM table GROUP BY category;

Table Macros

Convenience wrappers for per-group regression. All source columns are passed through to the output alongside predictions.

SELECT * FROM ols_fit_predict_by('sales', region, revenue, [ads, price]);

OLS Functions

anofox_stats_ols_fit

Ordinary Least Squares regression using SVD decomposition.

Signature:

anofox_stats_ols_fit(
    y LIST(DOUBLE),
    x LIST(LIST(DOUBLE)),
    [fit_intercept BOOLEAN DEFAULT true],
    [compute_inference BOOLEAN DEFAULT false],
    [confidence_level DOUBLE DEFAULT 0.95]
) -> STRUCT

Parameters:

ParameterTypeDescription
yLIST(DOUBLE)Response variable values
xLIST(LIST(DOUBLE))Feature arrays (each inner list is one feature)
fit_interceptBOOLEANInclude intercept term (default: true)
compute_inferenceBOOLEANCompute t-tests, p-values, CIs (default: false)
confidence_levelDOUBLECI confidence level (default: 0.95)

Returns: FitResult STRUCT

Example:

-- Simple regression: y = 2x + 1
SELECT anofox_stats_ols_fit(
    [3.0, 5.0, 7.0, 9.0, 11.0],
    [[1.0, 2.0, 3.0, 4.0, 5.0]]
);

-- With inference
SELECT anofox_stats_ols_fit(
    [3.0, 5.0, 7.0, 9.0, 11.0],
    [[1.0, 2.0, 3.0, 4.0, 5.0]],
    true, true, 0.95
);

anofox_stats_ols_fit_agg

Streaming OLS regression aggregate function.

Signature:

anofox_stats_ols_fit_agg(
    y DOUBLE,
    x LIST(DOUBLE),
    [fit_intercept BOOLEAN DEFAULT true],
    [compute_inference BOOLEAN DEFAULT false],
    [confidence_level DOUBLE DEFAULT 0.95]
) -> STRUCT

Example:

-- Per-group regression
SELECT
    category,
    (anofox_stats_ols_fit_agg(sales, [price, ads])).r_squared
FROM data
GROUP BY category;

-- Rolling regression (window function)
SELECT
    date,
    (anofox_stats_ols_fit_agg(y, [x]) OVER (
        ORDER BY date ROWS BETWEEN 9 PRECEDING AND CURRENT ROW
    )).coefficients[1] as rolling_beta
FROM time_series;

Ridge Functions

anofox_stats_ridge_fit

Ridge regression with L2 regularization.

Signature:

anofox_stats_ridge_fit(
    y LIST(DOUBLE),
    x LIST(LIST(DOUBLE)),
    alpha DOUBLE,
    [fit_intercept BOOLEAN DEFAULT true],
    [compute_inference BOOLEAN DEFAULT false],
    [confidence_level DOUBLE DEFAULT 0.95]
) -> STRUCT

Parameters:

ParameterTypeDescription
alphaDOUBLEL2 regularization strength (>= 0)

Example:

SELECT anofox_stats_ridge_fit(
    [2.1, 4.0, 5.9, 8.1, 10.0],
    [[1.0, 2.0, 3.0, 4.0, 5.0]],
    0.1  -- alpha
);

anofox_stats_ridge_fit_agg

Streaming Ridge regression aggregate function.

SELECT
    (anofox_stats_ridge_fit_agg(y, [x1, x2], 0.5)).coefficients
FROM data;

Elastic Net Functions

anofox_stats_elasticnet_fit

Elastic Net regression with combined L1/L2 regularization.

Signature:

anofox_stats_elasticnet_fit(
    y LIST(DOUBLE),
    x LIST(LIST(DOUBLE)),
    alpha DOUBLE,
    l1_ratio DOUBLE,
    [fit_intercept BOOLEAN DEFAULT true],
    [max_iterations INTEGER DEFAULT 1000],
    [tolerance DOUBLE DEFAULT 1e-6]
) -> STRUCT

Parameters:

ParameterTypeDescription
alphaDOUBLERegularization strength (>= 0)
l1_ratioDOUBLEL1 ratio: 0=Ridge, 1=Lasso (range: 0-1)
max_iterationsINTEGERMax coordinate descent iterations
toleranceDOUBLEConvergence tolerance

Example:

SELECT anofox_stats_elasticnet_fit(
    [2.1, 4.0, 5.9, 8.1, 10.0],
    [[1.0, 2.0, 3.0, 4.0, 5.0]],
    0.1,  -- alpha
    0.5   -- l1_ratio (50% L1, 50% L2)
);

anofox_stats_elasticnet_fit_agg

Streaming Elastic Net aggregate function.


WLS Functions

anofox_stats_wls_fit

Weighted Least Squares regression.

Signature:

anofox_stats_wls_fit(
    y LIST(DOUBLE),
    x LIST(LIST(DOUBLE)),
    weights LIST(DOUBLE),
    [fit_intercept BOOLEAN DEFAULT true],
    [compute_inference BOOLEAN DEFAULT false],
    [confidence_level DOUBLE DEFAULT 0.95]
) -> STRUCT

Parameters:

ParameterTypeDescription
weightsLIST(DOUBLE)Observation weights (same length as y)

Example:

SELECT anofox_stats_wls_fit(
    [3.0, 5.0, 7.0, 9.0, 11.0],
    [[1.0, 2.0, 3.0, 4.0, 5.0]],
    [1.0, 2.0, 3.0, 2.0, 1.0]  -- higher weight for middle observations
);

anofox_stats_wls_fit_agg

Streaming WLS aggregate function.

SELECT anofox_stats_wls_fit_agg(y, [x], weight) FROM data;

RLS Functions

anofox_stats_rls_fit

Recursive Least Squares for online/adaptive regression.

Signature:

anofox_stats_rls_fit(
    y LIST(DOUBLE),
    x LIST(LIST(DOUBLE)),
    [forgetting_factor DOUBLE DEFAULT 1.0],
    [fit_intercept BOOLEAN DEFAULT true],
    [initial_p_diagonal DOUBLE DEFAULT 100.0]
) -> STRUCT

Parameters:

ParameterTypeDescription
forgetting_factorDOUBLEExponential forgetting (0.95-1.0 typical)
initial_p_diagonalDOUBLEInitial covariance matrix diagonal

Example:

SELECT anofox_stats_rls_fit(
    [3.0, 5.0, 7.0, 9.0, 11.0],
    [[1.0, 2.0, 3.0, 4.0, 5.0]],
    0.99,  -- forgetting_factor
    true,  -- fit_intercept
    100.0  -- initial_p_diagonal
);

anofox_stats_rls_fit_agg

Streaming RLS aggregate function. Ideal for adaptive/online learning.

-- Adaptive regression with exponential forgetting
SELECT anofox_stats_rls_fit_agg(y, [x], 0.95) FROM streaming_data;

PLS Functions

Partial Least Squares regression for high-dimensional data and multicollinearity.

anofox_stats_pls_fit / pls_fit

PLS regression using the SIMPLS algorithm to find latent components that maximize covariance between X scores and y.

Signature:

anofox_stats_pls_fit(
    y LIST(DOUBLE),
    x LIST(LIST(DOUBLE)),
    [options MAP]
) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
n_componentsINTEGER2Number of latent components to extract
fit_interceptBOOLEANtrueInclude intercept term

Returns:

STRUCT(
    coefficients LIST(DOUBLE),  -- Regression coefficients
    intercept DOUBLE,           -- Intercept term (if fitted)
    r_squared DOUBLE,           -- Coefficient of determination
    n_components INTEGER,       -- Number of components used
    n_observations BIGINT,      -- Number of observations
    n_features INTEGER          -- Number of features
)

Example:

-- PLS with 3 components for high-dimensional data
SELECT pls_fit(
    [y1, y2, y3, y4, y5],
    [[x1_1, x1_2, x1_3, x1_4, x1_5],
     [x2_1, x2_2, x2_3, x2_4, x2_5],
     [x3_1, x3_2, x3_3, x3_4, x3_5]],
    {'n_components': 2}
);

-- Per-group PLS regression
SELECT
    category,
    (pls_fit_agg(y, [x1, x2, x3, x4, x5], {'n_components': 2})).r_squared
FROM high_dim_data
GROUP BY category;

Use Cases:

  • High-dimensional data (more features than observations)
  • Multicollinearity in predictors
  • Chemometrics and spectroscopy
  • Genomics and bioinformatics

anofox_stats_pls_fit_agg / pls_fit_agg

Streaming PLS regression aggregate function.

SELECT pls_fit_agg(y, [x1, x2, x3], {'n_components': 2}) FROM data;

Isotonic Functions

Isotonic regression for monotonic constraints.

anofox_stats_isotonic_fit / isotonic_fit

Fits a monotonic (non-decreasing or non-increasing) function to the data using pool adjacent violators algorithm (PAVA).

Signature:

anofox_stats_isotonic_fit(
    x LIST(DOUBLE),
    y LIST(DOUBLE),
    [options MAP]
) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
increasingBOOLEANtrueFit increasing (true) or decreasing (false) function

Returns:

STRUCT(
    fitted_values LIST(DOUBLE),  -- Monotonic fitted values
    r_squared DOUBLE,            -- Coefficient of determination
    n_observations BIGINT,       -- Number of observations
    increasing BOOLEAN           -- Direction of monotonicity
)

Example:

-- Fit increasing monotonic function (e.g., dose-response curve)
SELECT isotonic_fit(
    [1.0, 2.0, 3.0, 4.0, 5.0],
    [1.5, 2.0, 1.8, 3.5, 4.0],  -- Noisy but generally increasing
    {'increasing': true}
);

-- Decreasing isotonic regression (e.g., decay curve)
SELECT isotonic_fit(
    dose_levels,
    response_values,
    {'increasing': false}
);

Use Cases:

  • Dose-response modeling in pharmacology
  • Calibration curves
  • Monotonic trend estimation
  • Quality control thresholds

anofox_stats_isotonic_fit_agg / isotonic_fit_agg

Streaming isotonic regression aggregate function.

SELECT isotonic_fit_agg(x, y, {'increasing': true}) FROM calibration_data;

Quantile Functions

Quantile regression for estimating conditional quantiles.

anofox_stats_quantile_fit / quantile_fit

Quantile regression estimates conditional quantiles of the response variable distribution, rather than the conditional mean. Robust to outliers.

Signature:

anofox_stats_quantile_fit(
    y LIST(DOUBLE),
    x LIST(LIST(DOUBLE)),
    [options MAP]
) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
tauDOUBLE0.5Quantile to estimate (0 < tau < 1)
fit_interceptBOOLEANtrueInclude intercept term
max_iterationsINTEGER1000Maximum iterations
toleranceDOUBLE1e-6Convergence tolerance

Returns:

STRUCT(
    coefficients LIST(DOUBLE),  -- Regression coefficients
    intercept DOUBLE,           -- Intercept term (if fitted)
    tau DOUBLE,                 -- Quantile estimated
    n_observations BIGINT,      -- Number of observations
    n_features INTEGER          -- Number of features
)

Example:

-- Median regression (tau = 0.5) - robust to outliers
SELECT quantile_fit(
    [y1, y2, y3, y4, y5],
    [[x1, x2, x3, x4, x5]],
    {'tau': 0.5}
);

-- 90th percentile regression (upper bound estimation)
SELECT quantile_fit(
    prices,
    [size, location_score],
    {'tau': 0.9}
);

-- Compare different quantiles
SELECT
    0.25 as quantile, (quantile_fit(y, [x], {'tau': 0.25})).coefficients[1] as coef
UNION ALL
SELECT
    0.50 as quantile, (quantile_fit(y, [x], {'tau': 0.50})).coefficients[1] as coef
UNION ALL
SELECT
    0.75 as quantile, (quantile_fit(y, [x], {'tau': 0.75})).coefficients[1] as coef;

Use Cases:

  • Robust regression (outlier resistant)
  • Understanding full response distribution
  • Risk analysis (VaR, conditional tail expectations)
  • Heteroscedastic data analysis

anofox_stats_quantile_fit_agg / quantile_fit_agg

Streaming quantile regression aggregate function.

-- Per-group median regression
SELECT
    region,
    (quantile_fit_agg(price, [sqft, bedrooms], {'tau': 0.5})).coefficients
FROM housing
GROUP BY region;

GLM Functions

Generalized Linear Models for count data and other non-normal response distributions.

anofox_stats_poisson_fit_agg / poisson_fit_agg

Poisson regression for count data using maximum likelihood estimation.

Signature:

anofox_stats_poisson_fit_agg(
    y DOUBLE,
    x LIST(DOUBLE),
    [options MAP]
) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
fit_interceptBOOLEANtrueInclude intercept term
linkVARCHAR'log'Link function: 'log', 'identity', 'sqrt'
max_iterationsINTEGER100Maximum IRLS iterations
toleranceDOUBLE1e-8Convergence tolerance
compute_inferenceBOOLEANfalseCompute z-tests, p-values, CIs
confidence_levelDOUBLE0.95CI confidence level

Returns: GlmFitResult STRUCT

Example:

-- Basic Poisson regression for count data
SELECT poisson_fit_agg(count, [x1, x2])
FROM event_counts;

-- With inference and custom link
SELECT poisson_fit_agg(
    accidents,
    [traffic_volume, weather_score],
    {'compute_inference': true, 'link': 'log'}
)
FROM daily_accidents;

-- Per-group Poisson regression
SELECT
    region,
    (poisson_fit_agg(sales_count, [price, ads])).coefficients
FROM sales_data
GROUP BY region;

Use Cases:

  • Modeling count data (events, occurrences, frequencies)
  • Rate modeling with exposure offsets
  • Insurance claims, website visits, defect counts

ALM Functions

Augmented Linear Models with 24 error distribution families for flexible regression.

anofox_stats_alm_fit_agg / alm_fit_agg

Fit an Augmented Linear Model with choice of distribution and loss function.

Signature:

anofox_stats_alm_fit_agg(
    y DOUBLE,
    x LIST(DOUBLE),
    [options MAP]
) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
fit_interceptBOOLEANtrueInclude intercept term
distributionVARCHAR'normal'Error distribution (see below)
lossVARCHAR'likelihood'Loss function: 'likelihood', 'mse', 'mae', 'ham', 'role'
max_iterationsINTEGER100Maximum iterations
toleranceDOUBLE1e-8Convergence tolerance
quantileDOUBLE0.5Quantile for asymmetric_laplace
role_trimDOUBLE0.05Trim parameter for ROLE loss
compute_inferenceBOOLEANfalseCompute t-tests, p-values, CIs
confidence_levelDOUBLE0.95CI confidence level

Supported Distributions:

CategoryDistributions
Continuous (unbounded)normal, laplace, student_t, logistic, asymmetric_laplace, generalised_normal, s
Continuous (positive)log_normal, log_laplace, log_s, log_generalised_normal, gamma, inverse_gaussian, exponential
Continuous (bounded)folded_normal, rectified_normal, box_cox_normal, beta, logit_normal
Countpoisson, negative_binomial, binomial, geometric
Ordinalcumulative_logistic, cumulative_normal

Returns: AlmFitResult STRUCT

Example:

-- Robust regression with Laplace distribution (median regression)
SELECT alm_fit_agg(y, [x1, x2], {'distribution': 'laplace'})
FROM data_with_outliers;

-- Quantile regression (75th percentile)
SELECT alm_fit_agg(
    price,
    [sqft, bedrooms],
    {'distribution': 'asymmetric_laplace', 'quantile': 0.75}
)
FROM housing;

-- Gamma regression for positive data
SELECT alm_fit_agg(
    claim_amount,
    [age, risk_score],
    {'distribution': 'gamma', 'compute_inference': true}
)
FROM insurance_claims;

-- Beta regression for proportions (0-1)
SELECT alm_fit_agg(
    conversion_rate,
    [ad_spend, page_views],
    {'distribution': 'beta'}
)
FROM marketing_data;

Use Cases:

  • Robust regression (Laplace, Student-t)
  • Quantile regression (asymmetric_laplace)
  • Positive outcomes (gamma, log_normal)
  • Proportions/rates (beta, logit_normal)
  • Count data alternatives (negative_binomial)

BLS/NNLS Functions

Bounded Least Squares and Non-Negative Least Squares for constrained optimization.

anofox_stats_bls_fit_agg / bls_fit_agg

Bounded Least Squares with box constraints on coefficients.

Signature:

anofox_stats_bls_fit_agg(
    y DOUBLE,
    x LIST(DOUBLE),
    [options MAP]
) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
fit_interceptBOOLEANfalseInclude intercept term
lower_boundDOUBLE-Lower bound for all coefficients
upper_boundDOUBLE-Upper bound for all coefficients
max_iterationsINTEGER1000Maximum iterations
toleranceDOUBLE1e-10Convergence tolerance

Returns: BlsFitResult STRUCT

Example:

-- Coefficients bounded between 0 and 1
SELECT bls_fit_agg(
    y,
    [x1, x2, x3],
    {'lower_bound': 0.0, 'upper_bound': 1.0}
)
FROM portfolio_data;

-- Only lower bound (coefficients >= 0)
SELECT bls_fit_agg(
    y,
    [x1, x2],
    {'lower_bound': 0.0}
)
FROM data;

anofox_stats_nnls_fit_agg / nnls_fit_agg

Non-Negative Least Squares - all coefficients constrained to be >= 0.

Signature:

anofox_stats_nnls_fit_agg(
    y DOUBLE,
    x LIST(DOUBLE),
    [options MAP]
) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
fit_interceptBOOLEANfalseInclude intercept term
max_iterationsINTEGER1000Maximum iterations
toleranceDOUBLE1e-10Convergence tolerance

Returns: BlsFitResult STRUCT

Example:

-- Non-negative coefficients (e.g., mixture models)
SELECT nnls_fit_agg(spectrum, [component1, component2, component3])
FROM spectral_data;

-- Portfolio weights (no short selling)
SELECT nnls_fit_agg(returns, [stock1, stock2, stock3])
FROM portfolio_data;

-- Per-group NNLS
SELECT
    category,
    (nnls_fit_agg(y, [x1, x2])).coefficients
FROM data
GROUP BY category;

Use Cases:

  • Spectral unmixing / mixture models
  • Portfolio optimization without short selling
  • Physical constraints (concentrations, weights must be positive)
  • Image processing (non-negative matrix factorization)

AID Functions

AID (Automatic Identification of Demand) provides demand pattern classification and anomaly detection for time series data. Useful for inventory management, supply chain analysis, and demand forecasting.

anofox_stats_aid_agg / aid_agg

Classifies demand patterns as regular or intermittent, identifies best-fit distribution, and detects various anomaly patterns.

Signature:

anofox_stats_aid_agg(
    y DOUBLE,
    [options MAP]
) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
intermittent_thresholdDOUBLE0.3Zero proportion cutoff for intermittent classification
outlier_methodVARCHAR'zscore'Outlier detection: 'zscore' (mean±3σ) or 'iqr' (1.5×IQR)

Returns:

STRUCT(
    demand_type VARCHAR,           -- 'regular' or 'intermittent'
    is_intermittent BOOLEAN,       -- True if zero_proportion >= threshold
    distribution VARCHAR,          -- Best-fit distribution name
    mean DOUBLE,                   -- Mean of values
    variance DOUBLE,               -- Variance of values
    zero_proportion DOUBLE,        -- Proportion of zero values
    n_observations BIGINT,         -- Number of observations
    has_stockouts BOOLEAN,         -- True if stockouts detected
    is_new_product BOOLEAN,        -- True if new product pattern (leading zeros)
    is_obsolete_product BOOLEAN,   -- True if obsolete pattern (trailing zeros)
    stockout_count BIGINT,         -- Number of stockout observations
    new_product_count BIGINT,      -- Number of leading zero observations
    obsolete_product_count BIGINT, -- Number of trailing zero observations
    high_outlier_count BIGINT,     -- Number of unusually high values
    low_outlier_count BIGINT       -- Number of unusually low values
)

Distribution Selection:

  • Count-like data: poisson, negative_binomial, geometric
  • Continuous data: normal, gamma, lognormal, rectified_normal

Example:

-- Classify demand pattern for each SKU
SELECT
    sku,
    (aid_agg(demand)).*
FROM sales
GROUP BY sku;

-- With custom threshold
SELECT aid_agg(demand, {'intermittent_threshold': 0.4})
FROM sales
WHERE sku = 'WIDGET001';

-- Using IQR-based outlier detection
SELECT aid_agg(demand, {'outlier_method': 'iqr'})
FROM inventory_data;

anofox_stats_aid_anomaly_agg / aid_anomaly_agg

Returns per-observation anomaly flags for demand analysis. Maintains input order.

Signature:

anofox_stats_aid_anomaly_agg(
    y DOUBLE,
    [options MAP]
) -> LIST(STRUCT)

Options MAP:

KeyTypeDefaultDescription
intermittent_thresholdDOUBLE0.3Zero proportion cutoff
outlier_methodVARCHAR'zscore'Outlier detection: 'zscore' or 'iqr'

Returns:

LIST(STRUCT(
    stockout BOOLEAN,              -- Unexpected zero in positive demand
    new_product BOOLEAN,           -- Leading zeros pattern
    obsolete_product BOOLEAN,      -- Trailing zeros pattern
    high_outlier BOOLEAN,          -- Unusually high value
    low_outlier BOOLEAN            -- Unusually low value
))

Anomaly Definitions:

  • Stockout: Zero value occurring between non-zero values (not at start or end)
  • New Product: Leading sequence of zeros (before first non-zero)
  • Obsolete Product: Trailing sequence of zeros (after last non-zero)
  • High Outlier: Value > mean + 3std (zscore) or > Q3 + 1.5IQR (iqr)
  • Low Outlier: Non-zero value < mean - 3std (zscore) or < Q1 - 1.5IQR (iqr)

Example:

-- Get anomaly flags for demand series
SELECT aid_anomaly_agg(demand)
FROM (VALUES (0), (0), (5), (0), (8), (0), (0)) AS t(demand);
-- Returns: [
--   {stockout: false, new_product: true, ...},   -- Leading zero
--   {stockout: false, new_product: true, ...},   -- Leading zero
--   {stockout: false, new_product: false, ...},  -- First non-zero
--   {stockout: true, new_product: false, ...},   -- Stockout (zero between)
--   {stockout: false, new_product: false, ...},  -- Normal
--   {stockout: false, obsolete_product: true,...}, -- Trailing zero
--   {stockout: false, obsolete_product: true,...}  -- Trailing zero
-- ]

-- Identify problematic SKUs with stockouts
WITH anomalies AS (
    SELECT sku, aid_agg(demand) as result
    FROM sales
    GROUP BY sku
)
SELECT sku, result.stockout_count
FROM anomalies
WHERE result.has_stockouts
ORDER BY result.stockout_count DESC;

Use Cases:

  • Inventory management: Identify stockout patterns
  • Product lifecycle: Detect new/obsolete products
  • Demand forecasting: Choose appropriate models based on pattern type
  • Data quality: Find outliers in demand data
  • Supply chain: Monitor for demand anomalies

aid_by

Table macro that classifies demand patterns for each group, returning one row per group with flat columns.

Signature:

aid_by(
    source VARCHAR,           -- Table name (as string)
    group_col COLUMN,         -- Column to group by
    y_col COLUMN,             -- Demand/value column
    [options MAP]             -- Optional configuration (default: NULL)
) -> TABLE

Options:

KeyTypeDefaultDescription
intermittent_thresholdDOUBLE0.3Zero proportion cutoff for intermittent classification
outlier_methodVARCHAR'zscore'Outlier detection: 'zscore' (mean±3σ) or 'iqr' (1.5×IQR)

Returns:

ColumnTypeDescription
group_idANYGroup identifier (same type as group_col)
demand_typeVARCHAR'regular' or 'intermittent'
is_intermittentBOOLEANTrue if zero_proportion >= threshold
distributionVARCHARBest-fit distribution name
meanDOUBLEMean of values
varianceDOUBLEVariance of values
zero_proportionDOUBLEProportion of zero values (0.0 to 1.0)
n_observationsBIGINTNumber of observations
has_stockoutsBOOLEANTrue if stockouts detected
is_new_productBOOLEANTrue if new product pattern (leading zeros)
is_obsolete_productBOOLEANTrue if obsolete pattern (trailing zeros)
stockout_countBIGINTNumber of stockout observations
new_product_countBIGINTNumber of leading zero observations
obsolete_product_countBIGINTNumber of trailing zero observations
high_outlier_countBIGINTNumber of unusually high values
low_outlier_countBIGINTNumber of unusually low values

Example:

-- Classify demand pattern for each SKU
SELECT * FROM aid_by('sales', sku, demand);

-- With custom intermittent threshold
SELECT * FROM aid_by('sales', sku, demand, {'intermittent_threshold': 0.4});

-- Find products with stockout issues
SELECT * FROM aid_by('sales', sku, demand)
WHERE has_stockouts
ORDER BY stockout_count DESC;

Statistical Hypothesis Testing Functions

Comprehensive statistical hypothesis testing powered by the anofox-statistics crate. All tests are implemented as aggregate functions that collect data and compute test results.

Distributional Tests

shapiro_wilk_agg / anofox_stats_shapiro_wilk_agg

Shapiro-Wilk test for normality. Tests whether a sample comes from a normal distribution.

Signature:

shapiro_wilk_agg(value DOUBLE) -> STRUCT

Returns:

STRUCT(
    statistic DOUBLE,    -- W statistic (closer to 1 = more normal)
    p_value DOUBLE,      -- p-value (low = reject normality)
    n BIGINT,            -- Sample size
    method VARCHAR       -- "Shapiro-Wilk"
)

Example:

-- Test normality of residuals
SELECT (shapiro_wilk_agg(residual)).p_value as normality_p
FROM model_diagnostics;

-- Per-group normality test
SELECT
    category,
    (shapiro_wilk_agg(value)).*
FROM data
GROUP BY category;

Parametric Tests

t_test_agg / anofox_stats_t_test_agg

Two-sample t-test comparing means of two groups. Supports both Student's t-test (equal variances) and Welch's t-test (unequal variances).

Signature:

t_test_agg(value DOUBLE, group_id INTEGER, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
alternativeVARCHAR'two_sided''two_sided', 'less', 'greater'
confidence_levelDOUBLE0.95Confidence level for CI
kindVARCHAR'welch''welch' (default) or 'student' (var_equal=true)
muDOUBLE0.0Hypothesized mean difference

Returns:

STRUCT(
    statistic DOUBLE,     -- t-statistic
    p_value DOUBLE,       -- p-value
    df DOUBLE,            -- Degrees of freedom
    effect_size DOUBLE,   -- Cohen's d
    ci_lower DOUBLE,      -- CI lower bound
    ci_upper DOUBLE,      -- CI upper bound
    n1 BIGINT,            -- Group 1 sample size
    n2 BIGINT,            -- Group 2 sample size
    method VARCHAR        -- "Welch's t-test" or "Student's t-test"
)

Example:

-- Compare treatment vs control (group_id: 0 = control, 1 = treatment)
SELECT (t_test_agg(outcome, treatment_group)).*
FROM experiment;

-- One-sided test (treatment > control)
SELECT t_test_agg(score, group, {'alternative': 'greater'})
FROM test_results;

-- Student's t-test (assuming equal variances)
SELECT t_test_agg(value, group, {'kind': 'student'})
FROM data;

one_way_anova_agg / anofox_stats_one_way_anova_agg

One-way Analysis of Variance for comparing means across multiple groups.

Signature:

one_way_anova_agg(value DOUBLE, group_id INTEGER) -> STRUCT

Returns:

STRUCT(
    f_statistic DOUBLE,   -- F-statistic
    p_value DOUBLE,       -- p-value
    df_between BIGINT,    -- Between-groups degrees of freedom
    df_within BIGINT,     -- Within-groups degrees of freedom
    ss_between DOUBLE,    -- Between-groups sum of squares
    ss_within DOUBLE,     -- Within-groups sum of squares
    n_groups BIGINT,      -- Number of groups
    n BIGINT,             -- Total sample size
    method VARCHAR        -- "One-Way ANOVA"
)

Example:

-- Compare means across multiple treatment groups
SELECT (one_way_anova_agg(response, treatment_group)).*
FROM clinical_trial;

-- Per-study ANOVA
SELECT
    study_id,
    (one_way_anova_agg(value, condition)).p_value as anova_p
FROM multi_study_data
GROUP BY study_id;

Nonparametric Tests

mann_whitney_u_agg / anofox_stats_mann_whitney_u_agg

Mann-Whitney U test (Wilcoxon rank-sum test). Non-parametric alternative to independent t-test.

Signature:

mann_whitney_u_agg(value DOUBLE, group_id INTEGER, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
alternativeVARCHAR'two_sided''two_sided', 'less', 'greater'
confidence_levelDOUBLE0.95Confidence level for CI
correctionBOOLEANtrueApply continuity correction

Returns:

STRUCT(
    statistic DOUBLE,     -- U statistic
    p_value DOUBLE,       -- p-value
    effect_size DOUBLE,   -- Rank-biserial correlation
    ci_lower DOUBLE,      -- CI lower bound
    ci_upper DOUBLE,      -- CI upper bound
    n1 BIGINT,            -- Group 1 sample size
    n2 BIGINT,            -- Group 2 sample size
    method VARCHAR        -- "Mann-Whitney U"
)

Example:

-- Non-parametric comparison of two groups
SELECT (mann_whitney_u_agg(score, group)).*
FROM non_normal_data;

-- One-sided test
SELECT mann_whitney_u_agg(rating, condition, {'alternative': 'greater'})
FROM survey_results;

kruskal_wallis_agg / anofox_stats_kruskal_wallis_agg

Kruskal-Wallis H test. Non-parametric alternative to one-way ANOVA.

Signature:

kruskal_wallis_agg(value DOUBLE, group_id INTEGER) -> STRUCT

Returns:

STRUCT(
    statistic DOUBLE,    -- H statistic
    p_value DOUBLE,      -- p-value
    df DOUBLE,           -- Degrees of freedom (k-1)
    n BIGINT,            -- Total sample size
    method VARCHAR       -- "Kruskal-Wallis"
)

Example:

-- Non-parametric comparison of multiple groups
SELECT (kruskal_wallis_agg(satisfaction, department)).*
FROM employee_survey;

Correlation Tests

pearson_agg / anofox_stats_pearson_agg

Pearson product-moment correlation with significance test.

Signature:

pearson_agg(x DOUBLE, y DOUBLE, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
confidence_levelDOUBLE0.95Confidence level for CI

Returns:

STRUCT(
    r DOUBLE,             -- Correlation coefficient (-1 to 1)
    statistic DOUBLE,     -- t-statistic
    p_value DOUBLE,       -- p-value (test r ≠ 0)
    ci_lower DOUBLE,      -- CI lower bound (Fisher z-transformed)
    ci_upper DOUBLE,      -- CI upper bound
    n BIGINT,             -- Sample size
    method VARCHAR        -- "Pearson"
)

Example:

-- Test correlation between two variables
SELECT (pearson_agg(height, weight)).*
FROM measurements;

-- Per-group correlation with 99% CI
SELECT
    region,
    (pearson_agg(income, spending, {'confidence_level': 0.99})).*
FROM economic_data
GROUP BY region;

spearman_agg / anofox_stats_spearman_agg

Spearman rank correlation with significance test. Robust to outliers and non-linear relationships.

Signature:

spearman_agg(x DOUBLE, y DOUBLE, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
confidence_levelDOUBLE0.95Confidence level for CI

Returns: Same structure as pearson_agg with method "Spearman"

Example:

-- Rank correlation for ordinal data
SELECT (spearman_agg(rank_x, rank_y)).*
FROM ranked_data;

Categorical Tests

chisq_test_agg / anofox_stats_chisq_test_agg

Chi-square test of independence for categorical variables.

Signature:

chisq_test_agg(row_var INTEGER, col_var INTEGER, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
correctionBOOLEANfalseApply Yates' continuity correction

Returns:

STRUCT(
    statistic DOUBLE,    -- Chi-square statistic
    p_value DOUBLE,      -- p-value
    df BIGINT,           -- Degrees of freedom
    method VARCHAR       -- "Chi-Square"
)

Example:

-- Test independence of two categorical variables
SELECT (chisq_test_agg(gender, preference)).*
FROM survey;

-- With Yates correction for 2x2 tables
SELECT chisq_test_agg(group, outcome, {'correction': true})
FROM clinical_data;

chisq_gof_agg / anofox_stats_chisq_gof_agg

Chi-square goodness of fit test. Tests whether observed frequencies match expected frequencies.

Signature:

chisq_gof_agg(observed INTEGER, expected DOUBLE) -> STRUCT

Returns:

STRUCT(
    statistic DOUBLE,    -- Chi-square statistic
    p_value DOUBLE,      -- p-value
    df BIGINT,           -- Degrees of freedom
    method VARCHAR       -- "Chi-Square Goodness of Fit"
)

Example:

-- Test if observed frequencies match expected
SELECT (chisq_gof_agg(observed_count, expected_count)).*
FROM frequency_data;

g_test_agg / anofox_stats_g_test_agg

G-test (log-likelihood ratio test) for contingency tables.

Signature:

g_test_agg(row_var INTEGER, col_var INTEGER) -> STRUCT

Returns:

STRUCT(
    statistic DOUBLE,    -- G statistic
    p_value DOUBLE,      -- p-value
    df BIGINT,           -- Degrees of freedom
    method VARCHAR       -- "G-test"
)

Example:

-- G-test for independence
SELECT (g_test_agg(category_a, category_b)).*
FROM contingency_data;

fisher_exact_agg / anofox_stats_fisher_exact_agg

Fisher's exact test for 2x2 contingency tables.

Signature:

fisher_exact_agg(row_var INTEGER, col_var INTEGER, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
alternativeVARCHAR'two_sided''two_sided', 'less', 'greater'

Returns:

STRUCT(
    odds_ratio DOUBLE,   -- Odds ratio
    p_value DOUBLE,      -- p-value
    ci_lower DOUBLE,     -- CI lower bound
    ci_upper DOUBLE,     -- CI upper bound
    method VARCHAR       -- "Fisher's Exact Test"
)

Example:

-- Fisher's exact test for small samples
SELECT (fisher_exact_agg(treatment, outcome)).*
FROM small_study;

mcnemar_agg / anofox_stats_mcnemar_agg

McNemar's test for paired nominal data.

Signature:

mcnemar_agg(var1 INTEGER, var2 INTEGER, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
correctionBOOLEANtrueApply continuity correction

Returns:

STRUCT(
    statistic DOUBLE,    -- Chi-square statistic
    p_value DOUBLE,      -- p-value
    df BIGINT,           -- Degrees of freedom
    method VARCHAR       -- "McNemar's test"
)

Example:

-- Compare paired binary outcomes (before/after)
SELECT (mcnemar_agg(before_treatment, after_treatment)).*
FROM paired_study;

Effect Size Measures

cramers_v_agg / anofox_stats_cramers_v_agg

Cramér's V effect size for categorical association.

Signature:

cramers_v_agg(row_var INTEGER, col_var INTEGER) -> DOUBLE

Returns: Cramér's V coefficient (0 to 1)

Example:

-- Measure association strength
SELECT cramers_v_agg(category_a, category_b) as effect_size
FROM survey_data;

phi_coefficient_agg / anofox_stats_phi_coefficient_agg

Phi coefficient for 2x2 contingency tables.

Signature:

phi_coefficient_agg(row_var INTEGER, col_var INTEGER) -> DOUBLE

Returns: Phi coefficient (-1 to 1)

Example:

-- Phi coefficient for binary variables
SELECT phi_coefficient_agg(gender, preference) as phi
FROM binary_data;

contingency_coef_agg / anofox_stats_contingency_coef_agg

Pearson's contingency coefficient.

Signature:

contingency_coef_agg(row_var INTEGER, col_var INTEGER) -> DOUBLE

Returns: Contingency coefficient (0 to 1)

Example:

SELECT contingency_coef_agg(row_category, col_category) as c_coef
FROM categorical_data;

cohen_kappa_agg / anofox_stats_cohen_kappa_agg

Cohen's kappa for inter-rater agreement.

Signature:

cohen_kappa_agg(rater1 INTEGER, rater2 INTEGER) -> STRUCT

Returns:

STRUCT(
    kappa DOUBLE,        -- Kappa coefficient
    std_error DOUBLE,    -- Standard error
    z_value DOUBLE,      -- Z statistic
    p_value DOUBLE,      -- p-value
    ci_lower DOUBLE,     -- CI lower bound
    ci_upper DOUBLE,     -- CI upper bound
    method VARCHAR       -- "Cohen's Kappa"
)

Example:

-- Measure agreement between two raters
SELECT (cohen_kappa_agg(rater1_score, rater2_score)).*
FROM ratings;

Proportion Tests

prop_test_one_agg / anofox_stats_prop_test_one_agg

One-sample proportion test.

Signature:

prop_test_one_agg(successes INTEGER, trials INTEGER, p0 DOUBLE, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
alternativeVARCHAR'two_sided''two_sided', 'less', 'greater'
confidence_levelDOUBLE0.95Confidence level for CI

Returns:

STRUCT(
    statistic DOUBLE,    -- Z statistic
    p_value DOUBLE,      -- p-value
    estimate DOUBLE,     -- Sample proportion
    ci_lower DOUBLE,     -- CI lower bound
    ci_upper DOUBLE,     -- CI upper bound
    method VARCHAR       -- "One-sample proportion test"
)

Example:

-- Test if success rate differs from 50%
SELECT (prop_test_one_agg(successes, total, 0.5)).*
FROM experiment_results;

prop_test_two_agg / anofox_stats_prop_test_two_agg

Two-sample proportion test.

Signature:

prop_test_two_agg(successes INTEGER, trials INTEGER, group_id INTEGER, [options MAP]) -> STRUCT

Returns:

STRUCT(
    statistic DOUBLE,    -- Z statistic
    p_value DOUBLE,      -- p-value
    estimate1 DOUBLE,    -- Group 1 proportion
    estimate2 DOUBLE,    -- Group 2 proportion
    ci_lower DOUBLE,     -- CI lower bound for difference
    ci_upper DOUBLE,     -- CI upper bound for difference
    method VARCHAR       -- "Two-sample proportion test"
)

Example:

-- Compare conversion rates between groups
SELECT (prop_test_two_agg(conversions, visitors, ab_group)).*
FROM ab_test;

binom_test_agg / anofox_stats_binom_test_agg

Exact binomial test.

Signature:

binom_test_agg(successes INTEGER, trials INTEGER, p0 DOUBLE, [options MAP]) -> STRUCT

Returns:

STRUCT(
    p_value DOUBLE,      -- Exact p-value
    estimate DOUBLE,     -- Sample proportion
    ci_lower DOUBLE,     -- CI lower bound (Clopper-Pearson)
    ci_upper DOUBLE,     -- CI upper bound
    method VARCHAR       -- "Exact Binomial Test"
)

Example:

-- Exact test for small samples
SELECT (binom_test_agg(heads, flips, 0.5)).*
FROM coin_flip_data;

Additional Correlation Tests

kendall_agg / anofox_stats_kendall_agg

Kendall's tau rank correlation with significance test.

Signature:

kendall_agg(x DOUBLE, y DOUBLE, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
confidence_levelDOUBLE0.95Confidence level for CI

Returns:

STRUCT(
    tau DOUBLE,          -- Kendall's tau coefficient
    statistic DOUBLE,    -- Z statistic
    p_value DOUBLE,      -- p-value
    n BIGINT,            -- Sample size
    method VARCHAR       -- "Kendall"
)

Example:

-- Kendall correlation for ordinal data
SELECT (kendall_agg(rank_x, rank_y)).*
FROM ranked_data;

distance_cor_agg / anofox_stats_distance_cor_agg

Distance correlation for detecting nonlinear dependencies.

Signature:

distance_cor_agg(x DOUBLE, y DOUBLE) -> STRUCT

Returns:

STRUCT(
    dcor DOUBLE,         -- Distance correlation (0 to 1)
    dcov DOUBLE,         -- Distance covariance
    dvar_x DOUBLE,       -- Distance variance of x
    dvar_y DOUBLE,       -- Distance variance of y
    n BIGINT,            -- Sample size
    method VARCHAR       -- "Distance Correlation"
)

Example:

-- Detect nonlinear relationships
SELECT (distance_cor_agg(x, y)).*
FROM complex_relationships;

icc_agg / anofox_stats_icc_agg

Intraclass correlation coefficient.

Signature:

icc_agg(value DOUBLE, rater_id INTEGER, subject_id INTEGER, [options MAP]) -> STRUCT

Returns:

STRUCT(
    icc DOUBLE,          -- ICC value
    f_value DOUBLE,      -- F statistic
    df1 BIGINT,          -- Numerator df
    df2 BIGINT,          -- Denominator df
    p_value DOUBLE,      -- p-value
    ci_lower DOUBLE,     -- CI lower bound
    ci_upper DOUBLE,     -- CI upper bound
    method VARCHAR       -- "ICC"
)

Example:

-- Measure reliability across raters
SELECT (icc_agg(score, rater_id, subject_id)).*
FROM reliability_study;

Additional Parametric Tests

yuen_agg / anofox_stats_yuen_agg

Yuen's trimmed mean test (robust alternative to t-test).

Signature:

yuen_agg(value DOUBLE, group_id INTEGER, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
trimDOUBLE0.2Proportion to trim from each tail
alternativeVARCHAR'two_sided''two_sided', 'less', 'greater'

Returns:

STRUCT(
    statistic DOUBLE,    -- Test statistic
    p_value DOUBLE,      -- p-value
    df DOUBLE,           -- Degrees of freedom
    trimmed_mean1 DOUBLE,-- Group 1 trimmed mean
    trimmed_mean2 DOUBLE,-- Group 2 trimmed mean
    method VARCHAR       -- "Yuen's Trimmed Mean Test"
)

Example:

-- Robust comparison with outliers
SELECT (yuen_agg(score, treatment_group, {'trim': 0.1})).*
FROM data_with_outliers;

brown_forsythe_agg / anofox_stats_brown_forsythe_agg

Brown-Forsythe test for equality of variances.

Signature:

brown_forsythe_agg(value DOUBLE, group_id INTEGER) -> STRUCT

Returns:

STRUCT(
    statistic DOUBLE,    -- F statistic
    p_value DOUBLE,      -- p-value
    df1 BIGINT,          -- Numerator df
    df2 BIGINT,          -- Denominator df
    method VARCHAR       -- "Brown-Forsythe Test"
)

Example:

-- Test homogeneity of variances
SELECT (brown_forsythe_agg(measurement, group)).*
FROM multi_group_data;

Additional Nonparametric Tests

wilcoxon_signed_rank_agg / anofox_stats_wilcoxon_signed_rank_agg

Wilcoxon signed-rank test for paired samples.

Signature:

wilcoxon_signed_rank_agg(value1 DOUBLE, value2 DOUBLE, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
alternativeVARCHAR'two_sided''two_sided', 'less', 'greater'
correctionBOOLEANtrueApply continuity correction

Returns:

STRUCT(
    statistic DOUBLE,    -- W statistic
    p_value DOUBLE,      -- p-value
    n BIGINT,            -- Number of pairs
    method VARCHAR       -- "Wilcoxon Signed-Rank"
)

Example:

-- Paired nonparametric test (before/after)
SELECT (wilcoxon_signed_rank_agg(before, after)).*
FROM paired_measurements;

brunner_munzel_agg / anofox_stats_brunner_munzel_agg

Brunner-Munzel test (generalized Wilcoxon test).

Signature:

brunner_munzel_agg(value DOUBLE, group_id INTEGER, [options MAP]) -> STRUCT

Returns:

STRUCT(
    statistic DOUBLE,    -- Test statistic
    p_value DOUBLE,      -- p-value
    df DOUBLE,           -- Degrees of freedom
    estimate DOUBLE,     -- Probability estimate P(X < Y)
    method VARCHAR       -- "Brunner-Munzel"
)

Example:

-- Robust rank test
SELECT (brunner_munzel_agg(outcome, treatment_group)).*
FROM clinical_trial;

permutation_t_test_agg / anofox_stats_permutation_t_test_agg

Permutation t-test (resampling-based).

Signature:

permutation_t_test_agg(value DOUBLE, group_id INTEGER, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
n_permutationsINTEGER10000Number of permutations
alternativeVARCHAR'two_sided''two_sided', 'less', 'greater'

Returns:

STRUCT(
    statistic DOUBLE,    -- t statistic
    p_value DOUBLE,      -- Permutation p-value
    n_permutations BIGINT,
    method VARCHAR       -- "Permutation t-test"
)

Example:

-- Exact test via permutation
SELECT (permutation_t_test_agg(score, group, {'n_permutations': 5000})).*
FROM small_sample_data;

Normality Tests

dagostino_k2_agg / anofox_stats_dagostino_k2_agg

D'Agostino K² test for normality (based on skewness and kurtosis).

Signature:

dagostino_k2_agg(value DOUBLE) -> STRUCT

Returns:

STRUCT(
    statistic DOUBLE,    -- K² statistic
    p_value DOUBLE,      -- p-value
    skewness DOUBLE,     -- Sample skewness
    kurtosis DOUBLE,     -- Sample kurtosis
    n BIGINT,            -- Sample size
    method VARCHAR       -- "D'Agostino K²"
)

Example:

-- Test normality using skewness/kurtosis
SELECT (dagostino_k2_agg(residual)).*
FROM model_diagnostics;

Distribution Comparison

energy_distance_agg / anofox_stats_energy_distance_agg

Energy distance for comparing distributions.

Signature:

energy_distance_agg(value DOUBLE, group_id INTEGER) -> STRUCT

Returns:

STRUCT(
    distance DOUBLE,     -- Energy distance
    statistic DOUBLE,    -- Test statistic
    p_value DOUBLE,      -- p-value (permutation-based)
    method VARCHAR       -- "Energy Distance"
)

Example:

-- Compare two distributions
SELECT (energy_distance_agg(measurement, group)).*
FROM two_sample_data;

mmd_agg / anofox_stats_mmd_agg

Maximum Mean Discrepancy for distribution comparison.

Signature:

mmd_agg(value DOUBLE, group_id INTEGER, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
kernelVARCHAR'rbf'Kernel type: 'rbf', 'linear'
bandwidthDOUBLEautoRBF kernel bandwidth

Returns:

STRUCT(
    mmd DOUBLE,          -- MMD value
    mmd_squared DOUBLE,  -- MMD²
    p_value DOUBLE,      -- p-value
    method VARCHAR       -- "MMD"
)

Example:

-- Two-sample test using kernel methods
SELECT (mmd_agg(feature, sample_group)).*
FROM kernel_comparison;

Equivalence Tests (TOST)

tost_t_test_agg / anofox_stats_tost_t_test_agg

Two One-Sided Tests (TOST) for equivalence.

Signature:

tost_t_test_agg(value DOUBLE, group_id INTEGER, delta DOUBLE, [options MAP]) -> STRUCT

Parameters:

ParameterTypeDescription
deltaDOUBLEEquivalence margin (symmetric bounds)

Returns:

STRUCT(
    p_value DOUBLE,      -- TOST p-value (max of two one-sided)
    ci_lower DOUBLE,     -- 90% CI lower bound
    ci_upper DOUBLE,     -- 90% CI upper bound
    equivalent BOOLEAN,  -- True if equivalence established
    method VARCHAR       -- "TOST t-test"
)

Example:

-- Test equivalence within ±0.5
SELECT (tost_t_test_agg(outcome, treatment_group, 0.5)).*
FROM bioequivalence_study;

tost_paired_agg / anofox_stats_tost_paired_agg

TOST for paired samples.

Signature:

tost_paired_agg(value1 DOUBLE, value2 DOUBLE, delta DOUBLE, [options MAP]) -> STRUCT

Returns: Same structure as tost_t_test_agg

Example:

-- Paired equivalence test
SELECT (tost_paired_agg(method_a, method_b, 0.1)).*
FROM method_comparison;

tost_correlation_agg / anofox_stats_tost_correlation_agg

TOST for testing correlation equivalence to a reference value.

Signature:

tost_correlation_agg(x DOUBLE, y DOUBLE, rho0 DOUBLE, delta DOUBLE) -> STRUCT

Parameters:

ParameterTypeDescription
rho0DOUBLEReference correlation (typically 0)
deltaDOUBLEEquivalence margin around rho0

Returns:

STRUCT(
    r DOUBLE,            -- Sample correlation
    p_value DOUBLE,      -- TOST p-value
    ci_lower DOUBLE,     -- CI lower bound
    ci_upper DOUBLE,     -- CI upper bound
    equivalent BOOLEAN,  -- True if equivalence established
    method VARCHAR       -- "TOST Correlation"
)

Example:

-- Test if correlation is equivalent to zero (negligible relationship)
SELECT (tost_correlation_agg(x, y, 0.0, 0.1)).*
FROM correlation_study;

Forecast Evaluation

diebold_mariano_agg / anofox_stats_diebold_mariano_agg

Diebold-Mariano test for comparing forecast accuracy.

Signature:

diebold_mariano_agg(actual DOUBLE, forecast1 DOUBLE, forecast2 DOUBLE, [options MAP]) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
lossVARCHAR'mse'Loss function: 'mse', 'mae', 'mape'
alternativeVARCHAR'two_sided''two_sided', 'less', 'greater'

Returns:

STRUCT(
    statistic DOUBLE,    -- DM statistic
    p_value DOUBLE,      -- p-value
    loss1 DOUBLE,        -- Mean loss for forecast 1
    loss2 DOUBLE,        -- Mean loss for forecast 2
    method VARCHAR       -- "Diebold-Mariano"
)

Example:

-- Compare two forecasting models
SELECT (diebold_mariano_agg(actual, model1_pred, model2_pred)).*
FROM forecast_comparison;

clark_west_agg / anofox_stats_clark_west_agg

Clark-West test for nested model comparison.

Signature:

clark_west_agg(actual DOUBLE, forecast1 DOUBLE, forecast2 DOUBLE) -> STRUCT

Returns:

STRUCT(
    statistic DOUBLE,    -- CW statistic
    p_value DOUBLE,      -- p-value
    mspe_adj DOUBLE,     -- Adjusted MSPE difference
    method VARCHAR       -- "Clark-West"
)

Example:

-- Compare nested forecasting models
SELECT (clark_west_agg(actual, restricted_model, unrestricted_model)).*
FROM nested_model_comparison;

Statistical Test Aliases

Full NameShort Alias
anofox_stats_shapiro_wilk_aggshapiro_wilk_agg
anofox_stats_jarque_bera_aggjarque_bera_agg
anofox_stats_dagostino_k2_aggdagostino_k2_agg
anofox_stats_t_test_aggt_test_agg
anofox_stats_one_way_anova_aggone_way_anova_agg
anofox_stats_yuen_aggyuen_agg
anofox_stats_brown_forsythe_aggbrown_forsythe_agg
anofox_stats_mann_whitney_u_aggmann_whitney_u_agg
anofox_stats_kruskal_wallis_aggkruskal_wallis_agg
anofox_stats_wilcoxon_signed_rank_aggwilcoxon_signed_rank_agg
anofox_stats_brunner_munzel_aggbrunner_munzel_agg
anofox_stats_permutation_t_test_aggpermutation_t_test_agg
anofox_stats_pearson_aggpearson_agg
anofox_stats_spearman_aggspearman_agg
anofox_stats_kendall_aggkendall_agg
anofox_stats_distance_cor_aggdistance_cor_agg
anofox_stats_icc_aggicc_agg
anofox_stats_chisq_test_aggchisq_test_agg
anofox_stats_chisq_gof_aggchisq_gof_agg
anofox_stats_g_test_aggg_test_agg
anofox_stats_fisher_exact_aggfisher_exact_agg
anofox_stats_mcnemar_aggmcnemar_agg
anofox_stats_cramers_v_aggcramers_v_agg
anofox_stats_phi_coefficient_aggphi_coefficient_agg
anofox_stats_contingency_coef_aggcontingency_coef_agg
anofox_stats_cohen_kappa_aggcohen_kappa_agg
anofox_stats_prop_test_one_aggprop_test_one_agg
anofox_stats_prop_test_two_aggprop_test_two_agg
anofox_stats_binom_test_aggbinom_test_agg
anofox_stats_tost_t_test_aggtost_t_test_agg
anofox_stats_tost_paired_aggtost_paired_agg
anofox_stats_tost_correlation_aggtost_correlation_agg
anofox_stats_energy_distance_aggenergy_distance_agg
anofox_stats_mmd_aggmmd_agg
anofox_stats_diebold_mariano_aggdiebold_mariano_agg
anofox_stats_clark_west_aggclark_west_agg

Fit-Predict Window Functions

Window-based aggregate functions that fit a model incrementally and predict for each row. Use with OVER clause for rolling/expanding window regression.

anofox_stats_ols_fit_predict / ols_fit_predict

OLS regression with per-row predictions using window semantics.

Signature:

anofox_stats_ols_fit_predict(
    y DOUBLE,
    x LIST(DOUBLE),
    [options MAP]
) OVER (window_spec) -> STRUCT

Options MAP:

KeyTypeDefaultDescription
fit_interceptBOOLEANtrueInclude intercept term
confidence_levelDOUBLE0.95Prediction interval confidence
null_policyVARCHAR'drop'NULL handling: 'drop' or 'drop_y_zero_x'

Returns:

STRUCT(
    yhat DOUBLE,        -- Predicted value
    yhat_lower DOUBLE,  -- Lower prediction interval bound
    yhat_upper DOUBLE   -- Upper prediction interval bound
)

Example:

-- Expanding window: train on all previous rows, predict current
SELECT
    date,
    y,
    pred.yhat,
    pred.yhat_lower,
    pred.yhat_upper
FROM (
    SELECT
        date, y,
        ols_fit_predict(y, [x1, x2]) OVER (
            ORDER BY date
            ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
        ) as pred
    FROM time_series
);

-- Rolling 30-day window
SELECT
    date,
    ols_fit_predict(y, [x]) OVER (
        ORDER BY date
        ROWS BETWEEN 29 PRECEDING AND CURRENT ROW
    ) as pred
FROM daily_data;

-- Per-group expanding regression
SELECT
    category,
    date,
    ols_fit_predict(y, [x], {'confidence_level': 0.99}) OVER (
        PARTITION BY category
        ORDER BY date
    ) as pred
FROM grouped_data;

anofox_stats_ridge_fit_predict / ridge_fit_predict

Ridge regression with per-row predictions.

Additional Options:

KeyTypeDefaultDescription
alphaDOUBLE1.0L2 regularization strength
SELECT ridge_fit_predict(y, [x], {'alpha': 0.5}) OVER (ORDER BY date) FROM data;

anofox_stats_wls_fit_predict / wls_fit_predict

Weighted Least Squares with per-row predictions.

Signature:

wls_fit_predict(y DOUBLE, x LIST(DOUBLE), weight DOUBLE, [options MAP]) OVER (...)
SELECT wls_fit_predict(y, [x], weight) OVER (ORDER BY date) FROM data;

anofox_stats_rls_fit_predict / rls_fit_predict

Recursive Least Squares with per-row predictions.

Additional Options:

KeyTypeDefaultDescription
forgetting_factorDOUBLE1.0Exponential forgetting (0.95-1.0)
initial_p_diagonalDOUBLE100.0Initial covariance diagonal
SELECT rls_fit_predict(y, [x], {'forgetting_factor': 0.99}) OVER (ORDER BY date) FROM data;

anofox_stats_elasticnet_fit_predict / elasticnet_fit_predict

Elastic Net with per-row predictions.

Additional Options:

KeyTypeDefaultDescription
alphaDOUBLE1.0Regularization strength
l1_ratioDOUBLE0.5L1 ratio (0=Ridge, 1=Lasso)
max_iterationsINTEGER1000Max iterations
toleranceDOUBLE1e-6Convergence tolerance
SELECT elasticnet_fit_predict(y, [x], {'alpha': 0.1, 'l1_ratio': 0.7}) OVER (ORDER BY date) FROM data;

Fit-Predict Aggregate Functions

Non-rolling aggregate functions that fit a model once on training data (rows where y IS NOT NULL) and return predictions for ALL rows including out-of-sample predictions.

Deprecation Notice: The old *_predict_agg names (ols_predict_agg, ridge_predict_agg, etc.) are deprecated but still work for backwards compatibility. Use *_fit_predict_agg instead.

anofox_stats_ols_fit_predict_agg / ols_fit_predict_agg

Fit OLS on training rows, predict all rows.

Signature:

anofox_stats_ols_fit_predict_agg(
    y DOUBLE,
    x LIST(DOUBLE),
    [options MAP]
) -> LIST(STRUCT)

Options MAP:

KeyTypeDefaultDescription
fit_interceptBOOLEANtrueInclude intercept term
confidence_levelDOUBLE0.95Prediction interval confidence
null_policyVARCHAR'drop'NULL handling: 'drop' or 'drop_y_zero_x'

Returns:

LIST(STRUCT(
    y DOUBLE,           -- Original y value (NULL for out-of-sample)
    x LIST(DOUBLE),     -- Original x values
    yhat DOUBLE,        -- Predicted value
    yhat_lower DOUBLE,  -- Lower prediction interval bound
    yhat_upper DOUBLE,  -- Upper prediction interval bound
    is_training BOOLEAN -- True if row was used for training
))

Example:

-- Basic usage: fit on rows where y IS NOT NULL, predict all
CREATE TABLE data AS
SELECT
    CASE WHEN i <= 80 THEN i * 2.0 ELSE NULL END as y,
    i::DOUBLE as x,
    i as id
FROM range(1, 101) t(i);

-- Get predictions with training indicator
SELECT
    (p).y as original_y,
    (p).x as features,
    (p).yhat as predicted,
    (p).is_training
FROM (
    SELECT UNNEST(ols_fit_predict_agg(y, [x])) AS p
    FROM data
);

-- Per-group predictions
SELECT
    segment,
    UNNEST(ols_fit_predict_agg(y, [x1, x2], {'confidence_level': 0.99})) AS pred
FROM sales_data
GROUP BY segment;

anofox_stats_ridge_fit_predict_agg / ridge_fit_predict_agg

Ridge regression fit-predict aggregate.

Additional Options:

KeyTypeDefaultDescription
alphaDOUBLE1.0L2 regularization strength
SELECT UNNEST(ridge_fit_predict_agg(y, [x], {'alpha': 0.5})) FROM data;

anofox_stats_wls_fit_predict_agg / wls_fit_predict_agg

Weighted Least Squares fit-predict aggregate.

Signature:

wls_fit_predict_agg(y DOUBLE, x LIST(DOUBLE), weight DOUBLE, [options MAP]) -> LIST(STRUCT)
SELECT UNNEST(wls_fit_predict_agg(y, [x], weight)) FROM data;

anofox_stats_rls_fit_predict_agg / rls_fit_predict_agg

Recursive Least Squares fit-predict aggregate.

Additional Options:

KeyTypeDefaultDescription
forgetting_factorDOUBLE1.0Exponential forgetting
initial_p_diagonalDOUBLE100.0Initial covariance diagonal
SELECT UNNEST(rls_fit_predict_agg(y, [x], {'forgetting_factor': 0.99})) FROM data;

anofox_stats_elasticnet_fit_predict_agg / elasticnet_fit_predict_agg

Elastic Net fit-predict aggregate.

Additional Options:

KeyTypeDefaultDescription
alphaDOUBLE1.0Regularization strength
l1_ratioDOUBLE0.5L1 ratio (0=Ridge, 1=Lasso)
max_iterationsINTEGER1000Max iterations
toleranceDOUBLE1e-6Convergence tolerance
SELECT UNNEST(elasticnet_fit_predict_agg(y, [x], {'alpha': 0.1, 'l1_ratio': 0.5})) FROM data;

anofox_stats_bls_fit_predict_agg / bls_fit_predict_agg

Bounded Least Squares (BLS/NNLS) fit-predict aggregate with coefficient constraints.

Signature:

bls_fit_predict_agg(y DOUBLE, x LIST(DOUBLE), [options MAP]) -> LIST(STRUCT)

Options MAP:

KeyTypeDefaultDescription
lower_boundDOUBLE0.0Lower bound for coefficients
upper_boundDOUBLE+infUpper bound for coefficients
interceptBOOLEANfalseInclude intercept term
max_iterationsINTEGER1000Maximum iterations
toleranceDOUBLE1e-6Convergence tolerance
confidence_levelDOUBLE0.95Prediction interval confidence
null_policyVARCHAR'drop'NULL handling: 'drop' or 'drop_y_zero_x'

Example:

-- NNLS (Non-Negative Least Squares) with out-of-sample predictions
CREATE TABLE bounded_data AS
SELECT
    group_id, week, x,
    CASE WHEN week <= 10 THEN 5.0 + 2.0*x + RANDOM() ELSE NULL END AS y
FROM (VALUES (1), (2)) AS g(group_id),
     generate_series(1, 14) AS w(week),
     LATERAL (SELECT week * 1.5 AS x);

SELECT
    group_id,
    (pred).y AS actual,
    ROUND((pred).yhat, 2) AS predicted,
    (pred).is_training
FROM (
    SELECT group_id, UNNEST(bls_fit_predict_agg(y, [x], {'lower_bound': 0})) AS pred
    FROM bounded_data GROUP BY group_id
) sub;

anofox_stats_alm_fit_predict_agg / alm_fit_predict_agg

Augmented Linear Model fit-predict aggregate with robust error distributions.

Signature:

alm_fit_predict_agg(y DOUBLE, x LIST(DOUBLE), [options MAP]) -> LIST(STRUCT)

Options MAP:

KeyTypeDefaultDescription
distributionVARCHAR'normal'Error distribution (see below)
interceptBOOLEANtrueInclude intercept term
max_iterationsINTEGER1000Maximum iterations
toleranceDOUBLE1e-6Convergence tolerance
confidence_levelDOUBLE0.95Prediction interval confidence
null_policyVARCHAR'drop'NULL handling: 'drop' or 'drop_y_zero_x'

Distributions: normal, laplace, studentt, cauchy, huber, tukey, quantile, expectile, trimmed, winsorized

Example:

-- Robust regression with Laplace distribution (robust to outliers)
CREATE TABLE robust_data AS
SELECT
    group_id, x,
    CASE WHEN id <= 10 THEN
        CASE WHEN id = 5 THEN 100.0  -- Outlier
             ELSE 10.0 + 3.0*x + RANDOM()
        END
    ELSE NULL END AS y
FROM (VALUES (1), (2)) AS g(group_id),
     generate_series(1, 14) AS t(id),
     LATERAL (SELECT id * 2.0 AS x);

SELECT
    group_id,
    ROUND((pred).yhat, 2) AS predicted,
    (pred).is_training
FROM (
    SELECT group_id, UNNEST(alm_fit_predict_agg(y, [x], {'distribution': 'laplace'})) AS pred
    FROM robust_data GROUP BY group_id
) sub;

anofox_stats_poisson_fit_predict_agg / poisson_fit_predict_agg

Poisson GLM fit-predict aggregate for count data.

Signature:

poisson_fit_predict_agg(y DOUBLE, x LIST(DOUBLE), [options MAP]) -> LIST(STRUCT)

Options MAP:

KeyTypeDefaultDescription
linkVARCHAR'log'Link function: 'log', 'identity', 'sqrt'
interceptBOOLEANtrueInclude intercept term
max_iterationsINTEGER100Maximum IRLS iterations
toleranceDOUBLE1e-8Convergence tolerance
confidence_levelDOUBLE0.95Prediction interval confidence
null_policyVARCHAR'drop'NULL handling: 'drop' or 'drop_y_zero_x'

Example:

-- Poisson regression for visitor count prediction
CREATE TABLE visitor_data AS
SELECT
    store_id, week, marketing_spend,
    CASE WHEN week <= 10 THEN
        ROUND(EXP(2.0 + 0.05*marketing_spend) + RANDOM()*5)::INTEGER
    ELSE NULL END AS visitors
FROM (VALUES (1), (2), (3)) AS s(store_id),
     generate_series(1, 14) AS w(week),
     LATERAL (SELECT 20.0 + week*5.0 AS marketing_spend);

SELECT
    store_id,
    (pred).y AS actual_visitors,
    ROUND((pred).yhat) AS predicted_visitors,
    (pred).is_training
FROM (
    SELECT store_id, UNNEST(poisson_fit_predict_agg(visitors, [marketing_spend], {'link': 'log'})) AS pred
    FROM visitor_data GROUP BY store_id
) sub
WHERE store_id = 1;

Fit-Predict Table Macros

Table macros that wrap *_fit_predict_agg functions for easy per-group regression with long-format output. All source columns are passed through to the output, so you retain the original data alongside predictions.

All table macros accept an optional options MAP parameter to configure method-specific settings. When not provided, defaults are used.

ols_fit_predict_by

OLS regression per group with predictions in long format.

Signature:

ols_fit_predict_by(
    source VARCHAR,           -- Table name (as string)
    group_col COLUMN,         -- Column to group by
    y_col COLUMN,             -- Response variable column
    x_cols LIST(COLUMN),      -- Feature columns as list
    [options STRUCT],         -- Optional configuration (default: NULL)
    [split COLUMN]            -- Optional train/test split column (default: NULL)
) -> TABLE

Options:

KeyTypeDefaultDescription
fit_interceptBOOLEANtrueInclude intercept term
confidence_levelDOUBLE0.95Prediction interval confidence
null_policyVARCHAR'drop'NULL handling: 'drop' or 'drop_y_zero_x'

Returns:

All columns from the source table are preserved in the output (including the group column, y column, and all feature columns with their original names). The following prediction columns are appended:

ColumnTypeDescription
yhatDOUBLEPredicted value
yhat_lowerDOUBLELower prediction interval bound
yhat_upperDOUBLEUpper prediction interval bound
is_trainingBOOLEANTrue if row was used for training

Note: Column names in the output preserve the original names from the source table.

Example:

-- Per-group OLS regression
SELECT * FROM ols_fit_predict_by('sales_data', region, revenue, [advertising, price]);

-- With 99% prediction intervals
SELECT * FROM ols_fit_predict_by('sales_data', region, revenue, [advertising, price],
    {'confidence_level': 0.99});

-- Filter to out-of-sample predictions only
SELECT * FROM ols_fit_predict_by('forecast_data', store_id, sales, [inventory, promotions])
WHERE NOT is_training;

ridge_fit_predict_by

Ridge regression per group with predictions in long format.

Options:

KeyTypeDefaultDescription
alphaDOUBLE1.0L2 regularization strength
fit_interceptBOOLEANtrueInclude intercept term
confidence_levelDOUBLE0.95Prediction interval confidence
null_policyVARCHAR'drop'NULL handling

Example:

-- Ridge with default alpha
SELECT * FROM ridge_fit_predict_by('data', category, y, [x1, x2]);

-- Ridge with custom regularization
SELECT * FROM ridge_fit_predict_by('data', category, y, [x1, x2],
    {'alpha': 0.5});

-- Strong regularization
SELECT * FROM ridge_fit_predict_by('data', category, y, [x1, x2],
    {'alpha': 10.0, 'confidence_level': 0.99});

elasticnet_fit_predict_by

Elastic Net regression per group with predictions in long format.

Options:

KeyTypeDefaultDescription
alphaDOUBLE1.0Regularization strength
l1_ratioDOUBLE0.5L1 ratio: 0=Ridge, 1=Lasso
max_iterationsINTEGER1000Max coordinate descent iterations
toleranceDOUBLE1e-6Convergence tolerance
fit_interceptBOOLEANtrueInclude intercept term
confidence_levelDOUBLE0.95Prediction interval confidence
null_policyVARCHAR'drop'NULL handling

Example:

-- ElasticNet with default settings
SELECT * FROM elasticnet_fit_predict_by('data', category, y, [x1, x2]);

-- More Lasso-like (70% L1)
SELECT * FROM elasticnet_fit_predict_by('data', category, y, [x1, x2],
    {'alpha': 0.1, 'l1_ratio': 0.7});

wls_fit_predict_by

Weighted Least Squares per group with predictions in long format.

Signature:

wls_fit_predict_by(
    source VARCHAR,
    group_col COLUMN,
    y_col COLUMN,
    x_cols LIST(COLUMN),
    weight_col COLUMN,        -- Weight column (required)
    [options STRUCT]          -- Optional configuration (default: NULL)
) -> TABLE

Options:

KeyTypeDefaultDescription
fit_interceptBOOLEANtrueInclude intercept term
confidence_levelDOUBLE0.95Prediction interval confidence
null_policyVARCHAR'drop'NULL handling

Example:

-- WLS with weight column
SELECT * FROM wls_fit_predict_by('weighted_data', segment, y, [x1, x2], weight);

-- WLS with custom confidence level
SELECT * FROM wls_fit_predict_by('weighted_data', segment, y, [x1, x2], weight,
    {'confidence_level': 0.99});

rls_fit_predict_by

Recursive Least Squares per group with predictions in long format.

Options:

KeyTypeDefaultDescription
forgetting_factorDOUBLE1.0Exponential forgetting (0.95-1.0 typical)
initial_p_diagonalDOUBLE100.0Initial covariance diagonal
fit_interceptBOOLEANtrueInclude intercept term
confidence_levelDOUBLE0.95Prediction interval confidence
null_policyVARCHAR'drop'NULL handling

Example:

-- RLS with default settings
SELECT * FROM rls_fit_predict_by('streaming_data', sensor_id, reading, [temp, pressure]);

-- RLS with forgetting (adapts to recent data)
SELECT * FROM rls_fit_predict_by('streaming_data', sensor_id, reading, [temp, pressure],
    {'forgetting_factor': 0.95});

bls_fit_predict_by

Bounded Least Squares per group with predictions in long format.

Options:

KeyTypeDefaultDescription
lower_boundDOUBLE0.0Lower bound for coefficients
upper_boundDOUBLE+infUpper bound for coefficients
interceptBOOLEANfalseInclude intercept term
max_iterationsINTEGER1000Maximum iterations
toleranceDOUBLE1e-6Convergence tolerance
confidence_levelDOUBLE0.95Prediction interval confidence
null_policyVARCHAR'drop'NULL handling

Example:

-- BLS with default (non-negative coefficients)
SELECT * FROM bls_fit_predict_by('constrained_data', portfolio_id, returns, [factor1, factor2]);

-- Box constraints (coefficients between 0 and 1)
SELECT * FROM bls_fit_predict_by('portfolio_data', asset_class, returns, [factors],
    {'lower_bound': 0.0, 'upper_bound': 1.0});

alm_fit_predict_by

Augmented Linear Model per group with predictions in long format.

Options:

KeyTypeDefaultDescription
distributionVARCHAR'normal'Error distribution (see below)
interceptBOOLEANtrueInclude intercept term
max_iterationsINTEGER1000Maximum iterations
toleranceDOUBLE1e-6Convergence tolerance
confidence_levelDOUBLE0.95Prediction interval confidence
null_policyVARCHAR'drop'NULL handling

Distributions: normal, laplace, studentt, cauchy, huber, tukey, quantile, expectile, trimmed, winsorized

Example:

-- ALM with default (normal distribution)
SELECT * FROM alm_fit_predict_by('robust_data', group_id, y, [x1, x2]);

-- Robust regression with Laplace (median regression)
SELECT * FROM alm_fit_predict_by('data_with_outliers', group_id, y, [x1, x2],
    {'distribution': 'laplace'});

-- Student-t for heavy tails
SELECT * FROM alm_fit_predict_by('heavy_tailed_data', group_id, y, [x1, x2],
    {'distribution': 'studentt'});

poisson_fit_predict_by

Poisson GLM per group with predictions in long format.

Options:

KeyTypeDefaultDescription
linkVARCHAR'log'Link function: 'log', 'identity', 'sqrt'
interceptBOOLEANtrueInclude intercept term
max_iterationsINTEGER100Maximum IRLS iterations
toleranceDOUBLE1e-8Convergence tolerance
confidence_levelDOUBLE0.95Prediction interval confidence
null_policyVARCHAR'drop'NULL handling

Example:

-- Poisson with default log link
SELECT * FROM poisson_fit_predict_by('count_data', store_id, visitor_count, [marketing_spend]);

-- Poisson with identity link
SELECT * FROM poisson_fit_predict_by('count_data', store_id, visitor_count, [marketing_spend],
    {'link': 'identity'});

-- Poisson with custom iterations
SELECT * FROM poisson_fit_predict_by('count_data', store_id, visitor_count, [marketing_spend],
    {'link': 'log', 'max_iterations': 200});

Table Macro Aliases

MacroUnderlying AggregateMethod-Specific Options
ols_fit_predict_byols_fit_predict_agg(common only)
ridge_fit_predict_byridge_fit_predict_aggalpha
elasticnet_fit_predict_byelasticnet_fit_predict_aggalpha, l1_ratio, max_iterations, tolerance
wls_fit_predict_bywls_fit_predict_agg(common only)
rls_fit_predict_byrls_fit_predict_aggforgetting_factor, initial_p_diagonal
bls_fit_predict_bybls_fit_predict_agglower_bound, upper_bound, intercept, max_iterations, tolerance
alm_fit_predict_byalm_fit_predict_aggdistribution, intercept, max_iterations, tolerance
poisson_fit_predict_bypoisson_fit_predict_agglink, intercept, max_iterations, tolerance

Predict Function

anofox_stats_predict

Generate predictions using fitted coefficients.

Signature:

anofox_stats_predict(
    x LIST(LIST(DOUBLE)),
    coefficients LIST(DOUBLE),
    intercept DOUBLE
) -> LIST(DOUBLE)

Example:

-- First fit a model
WITH model AS (
    SELECT anofox_stats_ols_fit(y_values, x_values) as fit FROM training_data
)
-- Then predict
SELECT anofox_stats_predict(
    [[6.0, 7.0, 8.0]],  -- new x values
    model.fit.coefficients,
    model.fit.intercept
) as predictions
FROM model;

Diagnostic Functions

anofox_stats_vif / vif

Compute Variance Inflation Factor for multicollinearity detection.

Signature:

anofox_stats_vif(x LIST(LIST(DOUBLE))) -> LIST(DOUBLE)

Interpretation:

  • VIF = 1: No correlation
  • VIF > 5: Moderate correlation (warning)
  • VIF > 10: High correlation (problematic)

Example:

SELECT vif([[x1_vals], [x2_vals], [x3_vals]]) as vif_values;

anofox_stats_vif_agg / vif_agg

Streaming VIF aggregate function.

SELECT vif_agg([x1, x2, x3]) FROM data;

anofox_stats_aic / aic

Compute Akaike Information Criterion.

Signature:

anofox_stats_aic(rss DOUBLE, n BIGINT, k BIGINT) -> DOUBLE

Parameters:

ParameterTypeDescription
rssDOUBLEResidual Sum of Squares
nBIGINTNumber of observations
kBIGINTNumber of parameters (including intercept)

Example:

SELECT aic(100.0, 50, 3) as aic_value;

anofox_stats_bic / bic

Compute Bayesian Information Criterion.

Signature:

anofox_stats_bic(rss DOUBLE, n BIGINT, k BIGINT) -> DOUBLE

Example:

SELECT bic(100.0, 50, 3) as bic_value;

anofox_stats_jarque_bera / jarque_bera

Jarque-Bera test for normality of residuals.

Signature:

anofox_stats_jarque_bera(data LIST(DOUBLE)) -> STRUCT

Returns:

STRUCT(
    statistic DOUBLE,
    p_value DOUBLE,
    skewness DOUBLE,
    kurtosis DOUBLE,
    n BIGINT
)

Example:

SELECT jarque_bera(residuals).p_value as normality_pvalue;

anofox_stats_jarque_bera_agg / jarque_bera_agg

Streaming Jarque-Bera aggregate function.

SELECT jarque_bera_agg(residual) FROM fitted_data;

anofox_stats_residuals_diagnostics / residuals_diagnostics

Compute comprehensive residual diagnostics.

Signature:

anofox_stats_residuals_diagnostics(
    y LIST(DOUBLE),
    y_hat LIST(DOUBLE),
    [x LIST(LIST(DOUBLE))],
    [residual_std_error DOUBLE],
    [include_studentized BOOLEAN]
) -> STRUCT

Returns:

STRUCT(
    raw LIST(DOUBLE),
    standardized LIST(DOUBLE),
    studentized LIST(DOUBLE),
    leverage LIST(DOUBLE)
)

Example:

SELECT residuals_diagnostics(
    actual_values,
    predicted_values
) as diagnostics;

anofox_stats_residuals_diagnostics_agg / residuals_diagnostics_agg

Streaming residuals diagnostics aggregate function.


Common Options

null_policy Parameter

The null_policy option controls how NULL values are handled during model training.

ValueTraining SetPredictions
'drop' (default)Rows where y IS NOT NULLAll rows get predictions
'drop_y_zero_x'Rows where y IS NOT NULL AND all x != 0All rows get predictions

solver Parameter

Controls the matrix decomposition method for OLS, Ridge, and WLS.

ValueDescriptionBest for
'svd' (default)Singular Value DecompositionMost robust, handles rank-deficient matrices
'qr'QR DecompositionFaster for well-conditioned problems
'cholesky'Cholesky DecompositionFastest for positive-definite X'X

hc_type Parameter

Heteroscedasticity-consistent standard errors for OLS and WLS. Requires compute_inference: true.

ValueDescription
'none' (default)Classical (homoscedastic) standard errors
'hc0'White's estimator
'hc1'HC0 with degrees-of-freedom correction
'hc2'HC0 with leverage adjustment
'hc3'HC0 with squared leverage adjustment (most conservative)

lambda_scaling Parameter

Controls the lambda scaling convention for Ridge and Elastic Net.

ValueDescription
'raw' (default)Lambda is used as-is in the penalty term
'glmnet'Lambda is scaled by 1/(2n) to match glmnet convention

glm_lambda Parameter

L2 regularization for Poisson GLM. Set to 0.0 (default) for no regularization.


Return Types

FitResult Structure

Standard return type for linear regression functions.

STRUCT(
    coefficients LIST(DOUBLE),
    intercept DOUBLE,
    r_squared DOUBLE,
    adj_r_squared DOUBLE,
    mse DOUBLE,
    rmse DOUBLE,
    mae DOUBLE,
    rss DOUBLE,
    tss DOUBLE,
    n_observations BIGINT,
    n_features INTEGER,
    -- When compute_inference=true:
    t_statistics LIST(DOUBLE),
    p_values LIST(DOUBLE),
    std_errors LIST(DOUBLE),
    conf_int_lower LIST(DOUBLE),
    conf_int_upper LIST(DOUBLE)
)

Accessing Results

-- Extract specific fields
SELECT
    (result).r_squared,
    (result).coefficients[1] as beta1,
    (result).coefficients[2] as beta2
FROM (SELECT ols_fit_agg(y, [x1, x2]) as result FROM data);

-- Expand all fields
SELECT (ols_fit_agg(y, [x1, x2])).* FROM data;

Short Aliases

Most functions have short aliases without the anofox_stats_ prefix:

Full NameAlias
anofox_stats_ols_fitols_fit
anofox_stats_ridge_fitridge_fit
anofox_stats_t_test_aggt_test_agg
anofox_stats_pearson_aggpearson_agg
......

Detailed Documentation

For comprehensive documentation on each function category:


Error Handling

All functions return NULL on error conditions:

  • Invalid input types
  • Empty arrays
  • Singular matrices (insufficient data variation)

Check for NULL results when using these functions:

SELECT COALESCE((ols_fit_agg(y, [x])).r_squared, 0.0) as r_squared
FROM data;

Performance Notes

  • Aggregate functions are generally preferred for large datasets as they process data in a streaming fashion
  • Scalar functions may be faster for small, pre-aggregated arrays
  • Use table macros for the simplest syntax when doing per-group predictions
  • VIF computation is O(k³) where k is the number of features

Version History

  • 0.6.0: Added aid_anomaly_by table macro, reorganized documentation
  • 0.5.0: Added PLS, Isotonic, Quantile regression
  • 0.4.0: Added ALM with 24 distributions
  • 0.3.0: Added comprehensive hypothesis testing
  • 0.2.0: Added BLS/NNLS, RLS
  • 0.1.0: Initial release with OLS, Ridge, Elastic Net, WLS