Rust-powered customer segmentation with a Python API: RFM analysis, clustering, churn scoring, CLV, and privacy-aware audience tooling in one dependency.
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).
| 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).
- 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_sqlgenerates 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.
Segment and membership output has a versioned Squid-CRM custom-object contract:
schemas/squid/v1/segment.schema.json—audienceSegmentsschemas/squid/v1/segment-membership.schema.json—audienceSegmentMembershipsclusteraudiencekit/squid.py— stable ids, metadata manifest, record mapping, batched lookup/upsert plan and a deterministicIdempotency-Keydocs/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.
- 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.
AudienceSegmenterdoes 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), andsegment_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.
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.
pip install clusteraudiencekitRequires 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).
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)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.
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).
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.
- Honest roadmap — what's real, what's deferred, and why.
- Architecture — real module layout and data flow, checked
against
src/. - Security audit
- SQL export reference
- Examples
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.
AudienceSegmenterdoes not standardize inputs, and neither the quick-start example norassess_cluster_qualitywarns 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.0remains 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.anyhow1.0.102 has an unsoundness advisory inError::downcast_mut()(RUSTSEC-2026-0190); tracked in RepoIssues #34.- Two Rust utility functions are unimplemented stubs.
pandas_to_arrow/arrow_to_pandasinsrc/utils/conversions.rsreturnErr("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").
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.
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 testsNote 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.
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.jsonto flag risky tests, map blast radius, and estimate test cost.
Apache License 2.0. See LICENSE for the full terms.