Skip to content

About

Enterprise audience intelligence at scale. RFM analysis, 3 clustering algorithms (K-Means, K-Prototypes, Mini-Batch K-Means), CLV, churn detection, lookalikes.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

195 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

ClusterAudienceKit

Rust-powered customer segmentation with a Python API: RFM analysis, clustering, churn scoring, CLV, and privacy-aware audience tooling in one dependency.

License: Apache 2.0 PyPI Python 3.8+ Tests

What it is

ClusterAudienceKit is a Rust-powered customer segmentation engine with Python bindings. It covers RFM analysis, KMeans/K-Prototypes clustering, cluster-quality metrics, automatic K selection, churn prediction, customer lifetime value, SQL export to 8 warehouse dialects, differential privacy / k-anonymity, real-time streaming segmentation, drift detection, lookalike audiences, cohort analytics, lifecycle tracking, rule-based behavioral segmentation, segment profiling, temporal size/composition forecasting, historical reconstruction, trend momentum, what-if scenario simulation, price elasticity, price tier migration, category affinity, discount optimization, segment ROI, customer acquisition cost, revenue attribution and forecasting, and a small neural-network regressor — all real, tested Rust logic exposed through the compiled Python extension (import clusteraudiencekit).

Features

Capability Python entry points
RFM analysis calculate_rfm, RFMConfig, RFMScore
KMeans / K-Prototypes clustering kmeans, AudienceSegmenter
Cluster quality metrics silhouette_score, davies_bouldin_score, calinski_harabasz_score, assess_cluster_quality
Automatic K selection estimate_k_elbow, estimate_k_gap_statistic, estimate_k_silhouette, estimate_k_combined
Churn prediction (incl. real AUC-ROC) ChurnPrediction, ChurnRiskLevel
Customer lifetime value CustomerLTV, calculate_simple_ltv
SQL export (8 dialects, injection-safe) export_segment_sql, export_all_segments_sql, get_supported_sql_dialects
Differential privacy & k-anonymity PyPrivacyBudget, add_laplace_noise, add_gaussian_noise, check_k_anonymity, suppress_to_k_anonymous, generalize_numeric
Real-time streaming segmentation PyStreamingSegmentationEngine, PyStreamingEvent, PyStreamingConfig
Drift detection kolmogorov_smirnov, hellinger_distance, chi_square_drift, detect_feature_drift, detect_segment_composition_change
Lookalike audiences generate_lookalike, find_similar_customers, cosine_similarity
Cohort analytics create_cohort, cohort_id_for, compare_cohorts, aggregate_cohorts_by_period, cohort_retention_table
Lifecycle tracking classify_lifecycle_stage, lifecycle_retention_actions, lifecycle_stage_distribution
Rule-based behavioral segmentation PyBehavioralSegmenter, PyBehavioralSegment, PyBehavioralRule, PyCondition
Segment profiling profile_segment
Temporal size forecasting forecast_segment_sizes, SizeForecast
Historical reconstruction reconstruct_segment_history, HistoricalSegmentState
Trend momentum analyze_trend_momentum, TrendMomentum
Composition forecasting forecast_composition, CompositionForecast
What-if scenario simulation simulate_what_if, WhatIfScenario
Price elasticity analyze_price_elasticity, ElasticityAnalysis
Price tier migration predict_tier_migration, TierMigrationForecast
Category affinity analyze_category_affinity, CategoryAffinity
Discount optimization optimize_discount, DiscountStrategy
Segment ROI calculate_segment_roi, SegmentROI
Customer acquisition cost calculate_cac, CustomerAcquisitionCost
Revenue attribution calculate_revenue_attribution, RevenueAttribution
Revenue forecasting forecast_revenue, RevenueForecast
Neural-network regressor NeuralNetwork, TrainingStats

Segmentation output is 13 named RFM segments (Champions, Loyal Customers, Potential Loyalists, At Risk, Cannot Lose Them, About to Sleep, New Customers, Promising, Need Attention, Lost, At Risk - Sleeping, Hibernating, VIP).

Who it's for

  • Marketing and data teams building a segmentation pipeline on a large transaction table where scikit-learn's Python-level clustering is the bottleneck — the Rust core is rayon-parallelized and deterministic for a given seed.
  • Teams exporting customer segments directly into a warehouse — export_segment_sql generates injection-safe SQL for 8 dialects rather than hand-writing per-warehouse export scripts.
  • Privacy-constrained segmentation — differential privacy (Laplace/Gaussian noise) and k-anonymity suppression/generalization are real, tested primitives, not a compliance checkbox.

Squid segment contract

Segment and membership output has a versioned Squid-CRM custom-object contract:

  • schemas/squid/v1/segment.schema.json — audienceSegments
  • schemas/squid/v1/segment-membership.schema.json — audienceSegmentMemberships
  • clusteraudiencekit/squid.py — stable ids, metadata manifest, record mapping, batched lookup/upsert plan and a deterministic Idempotency-Key
  • docs/SQUID_SEGMENTS.md — field definitions, sequence, acceptance checklist and limits

The helper is pure data: no HTTP client, credentials or live writes. customerId is opaque, email-like values are rejected, and no consent decision is stored in a segment record.

What it is not

  • Not external platform activation. The library does not push segments to ad/CRM platforms over HTTP. It does define a versioned Squid-CRM custom-object contract and a pure-data lookup/upsert plan (clusteraudiencekit/squid.py, docs/SQUID_SEGMENTS.md); Squid acceptance and a live write test remain pending. B2B governance/workflow tooling, a dashboard UI, and a plugin framework are also out of scope.
  • Not a scikit-learn wrapper. The algorithms are real, independently unit-tested Rust implementations, not thin bindings over Python libraries.
  • Not feature-scaling-aware by default. AudienceSegmenter does no internal standardization; on real data you should standardize recency/frequency/monetary yourself before calling .fit() (see Known issues).
  • K-Prototypes categorical support is partial. AudienceSegmenter.fit() accepts only a numeric feature matrix today, so selecting K-Prototypes through that class runs numeric-only (effectively KMeans). The underlying Rust implementation does support mixed data; it just isn't reachable from that Python entry point yet.
  • Six Rust modules are only partially exposed to Python. Each has real, tested, stateless slices wired up: temporal_analytics (forecast_segment_sizes, forecast_composition, simulate_what_if, reconstruct_segment_history, analyze_trend_momentum), price_intelligence (analyze_price_elasticity, optimize_discount, predict_tier_migration, analyze_category_affinity), revenue_intelligence (calculate_segment_roi, calculate_revenue_attribution, forecast_revenue, calculate_cac), neural_networks (NeuralNetwork, TrainingStats), pattern_discovery (SegmentTrend, EmergingAudience), and segment_intelligence (SegmentConfidence, SegmentEntropy, SegmentDifferentiation, SegmentPredictability, SegmentAging). Their remaining APIs (margin/bundle optimization, membership/churn/lifecycle forecasting, scenario comparison, autoencoder/RNN, and similar) are a follow-up release. Everything exposed is tested, not a stub.

Project status

Production/Stable per the package classifier (version 7.5.2), with the honest gaps above. This project tracks its own implementation-vs.-plan status on purpose; see docs/ROADMAP_HONEST.md. Changes are tracked in CHANGELOG.md.

Installation

pip install clusteraudiencekit

Requires Python 3.8+, with NumPy, Pandas, and PyArrow (see pyproject.toml for exact ranges). The compiled Rust core ships as a platform wheel, so no local Rust toolchain is needed — but the only wheel currently published to PyPI is macOS ARM64 (cp39-abi3), alongside an sdist. On any other platform, pip install falls back to building the sdist from source, which does require a Rust toolchain; or clone the repo and build locally with maturin (pip install maturin && maturin develop --release).

Quick start

from clusteraudiencekit import AudienceSegmenter, RFMConfig, calculate_rfm

# transactions: list of (customer_id, iso8601_date, amount).
# n_clusters must be <= the number of distinct customers — use your real,
# larger transaction history here; this toy example has 3 customers.
transactions = [
    ("cust_1", "2026-06-01T00:00:00+00:00", 120.0),
    ("cust_1", "2026-07-15T00:00:00+00:00", 80.0),
    ("cust_2", "2026-01-10T00:00:00+00:00", 15.0),
    ("cust_3", "2026-08-01T00:00:00+00:00", 500.0),
]

# Real RFM scoring (recency/frequency/monetary, quintile-scored, 13-segment
# classification), not a mock.
scores = calculate_rfm(transactions, RFMConfig())

# Cluster customers by their RFM features with real KMeans (k-means++ init,
# rayon-parallelized assignment step, deterministic for a given seed).
features = [[s.recency, s.frequency, s.monetary] for s in scores]
segmenter = AudienceSegmenter(2)
segmenter.fit(features)
segments = segmenter.predict(features)

Preprocessing before clustering

Distance-based clustering needs comparable numeric features. Install the optional sklearn/pandas adapter:

pip install "clusteraudiencekit[preprocessing]"
from clusteraudiencekit import AudienceSegmenter, fit_with_preprocessing

wrapped = fit_with_preprocessing(
    AudienceSegmenter(n_clusters=4),
    customers_df,
    numeric_features=["recency", "frequency", "monetary"],
    categorical_features=["channel", "region"],
)
labels = wrapped.predict(customers_df)

PreprocessingPipeline fits median imputation, standard scaling and one-hot encoding, and reuses those fitted statistics at predict time. It is optional; the Rust engine itself remains dependency-free.

Usage

Why ClusterAudienceKit?

Marketing/data teams need RFM segmentation, clustering, churn scoring, and CLV estimation, usually stitched together from several tools. This package does the core numeric work in Rust (fast, deterministic, real unit-tested algorithms — not scikit-learn wrappers) with a Python API, so you get one dependency instead of five, and you can inspect exactly what's real (see docs/ROADMAP_HONEST.md).

vs scikit-learn & lifetimes

No single OSS package covers everything here, so this compares the two pieces with direct real competitors: clustering vs scikit-learn's KMeans, and CLV vs the lifetimes package's real BG/NBD probabilistic model. Tested against a real public e-commerce dataset — the UCI "Online Retail" transaction log (541,909 real transactions, cleaned to 397,884 real rows / 4,338 real customers with valid quantity/price/customer ID) — not synthetic data.

ClusterAudienceKit scikit-learn
RFM computation (4,338 real customers) 0.026s — (not scikit-learn's job)
KMeans, K=5, on raw RFM features 0.001s, silhouette=0.9502 0.025s (unscaled, matching CAK's real input), silhouette=0.8387, RuntimeWarning: overflow encountered in matmul
KMeans, K=5, standardized features — (no built-in scaling) 0.080s, silhouette=0.7744

The silhouette numbers above are misleading on their own, and this is the real, important finding, not the timing. Inspecting the actual cluster sizes on real, unscaled RFM features: 4,300 of 4,338 real customers (99.1%) land in one giant cluster, with 4 tiny outlier clusters splitting off customers with extreme real monetary values (one real customer spent $280,206 vs. a $2,054 mean). That's a textbook unscaled-KMeans failure — monetary has ~450x the numeric range of recency/frequency, so raw Euclidean distance is dominated by it, and the "high" silhouette score is an artifact of that degenerate split, not good segmentation. Standardize recency/frequency/monetary yourself (e.g. sklearn.preprocessing.StandardScaler) before calling .fit() on real data.

ClusterAudienceKit calculate_simple_ltv lifetimes (BG/NBD + Gamma-Gamma)
Method Deterministic: (total_spent / days_active) * 365 * lifespan_years Real probabilistic model fit on repeat-purchase patterns
Repeat-purchaser customers scored by both 2,790 real customers 2,790 real customers
Rank correlation (Spearman ρ) between the two tools' CLV rankings 0.7111 (p < 1e-300) —

A substantial, real positive correlation — the two independently-computed approaches broadly agree on who a business's most valuable real customers are.

Documentation

Known issues

Verified as of the last audit (October 2026):

  • The only wheel on PyPI is macOS ARM64 (cp39-abi3), plus an sdist. A multi-platform wheel-building CI workflow (.github/workflows/wheels.yml) builds and tests wheels on Linux, macOS (arm64 + x86_64), and Windows, and is wired to publish via Trusted Publishing on tagged releases; the PyPI-side Trusted Publisher still has to be configured before that job can succeed.
  • No internal feature standardization. AudienceSegmenter does not standardize inputs, and neither the quick-start example nor assess_cluster_quality warns about the unscaled-KMeans failure described above. Standardize your features first on real data.
  • K-Prototypes categorical support is partial (numeric-only through AudienceSegmenter.fit(); see above).
  • v7.0.0 remains installable from PyPI despite a confirmed import-crashing bug. If you have it pinned, upgrade to >=7.2.0.
  • cargo audit: 1 open advisory with no fix available. anyhow 1.0.102 has an unsoundness advisory in Error::downcast_mut() (RUSTSEC-2026-0190); tracked in RepoIssues #34.
  • Two Rust utility functions are unimplemented stubs. pandas_to_arrow/arrow_to_pandas in src/utils/conversions.rs return Err("Not implemented"); they aren't called elsewhere or exposed to Python.
  • Six tested Rust modules are only partially wired to the Python API — each exposes a small stateless slice, with the rest deferred (see "What it is not").

Known issues and deferred work

Blocked / failed:

  • Linux/Windows wheels.
  • CLV/churn validation against lifetimes/PyMC-Marketing.

Rejected / deferred:

  • A full CDP or warehouse; integrate with MessageBirds/PyReverseETL.

Full shipped/blocked/rejected detail: docs/internal/QUEUE_STATUS.md.

Contributing

See CONTRIBUTING.md. Development quickstart:

maturin develop --release            # build the Rust extension + install editable
cargo test --no-default-features     # Rust unit tests
pytest tests/ -v                     # Python tests

Note the --no-default-features flag: the default extension-module feature omits linking against libpython, which a standalone cargo test binary needs. See CONTRIBUTING.md and docs/ROADMAP_HONEST.md for details.

Related projects

Other tools from the same family, for adjacent parts of the customer/data stack:

  • PyReverseETL — reverse ETL runtime: move data into CRMs and marketing tools with lineage and compliance enforcement.
  • PySynthData — synthetic data generation for ML training: realistic datasets for model development and testing.
  • StatGuardian — fast, declarative data quality framework (Rust): schema validation, drift detection, anomaly detection.
  • PyWeatherEnriched — real historical weather and geocoding enrichment for ML pipelines.
  • PyDBTGuard — analyzes a dbt project's manifest.json to flag risky tests, map blast radius, and estimate test cost.

Browse all projects →

License

Apache License 2.0. See LICENSE for the full terms.

About

Enterprise audience intelligence at scale. RFM analysis, 3 clustering algorithms (K-Means, K-Prototypes, Mini-Batch K-Means), CLV, churn detection, lookalikes.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages