Skip to main content

CardinalityKit

A comprehensive Python toolkit for cardinality estimation algorithms, enabling privacy-preserving analytics through probabilistic counting techniques.

What is CardinalityKit?

CardinalityKit provides implementations of state-of-the-art algorithms for estimating the number of unique elements in large datasets without storing individual values. This is crucial for:

  • Privacy-Preserving Analytics: Count unique users without exposing individual identifiers
  • Memory Efficiency: Use minimal memory regardless of dataset size
  • Cross-Platform Deduplication: Estimate unique reach across multiple platforms
  • Sample-Based Extrapolation: Convert panel data to population-level estimates

Features

Core Algorithms

  • Flajolet-Martin: Historical probabilistic counting algorithm
  • LogLog: Improved memory efficiency with bucket averaging
  • SuperLogLog: Enhanced accuracy with outlier elimination
  • HyperLogLog (HLL): Industry-standard algorithm (used by Redis, PostgreSQL)
  • HyperReal (HR): Unbiased estimation for research applications

Extended Algorithms

  • Extended HyperLogLog: HLL with demographic attribute tracking
  • Extended HyperReal: HR with demographic attribute tracking
  • Support for audience segmentation while maintaining privacy

Sample Conversion

  • Naive Association: Simple sample-to-population conversion
  • Fast Association: Optimized conversion with configurable precision
  • Convert survey/panel data to full population estimates

Installation

pip install cardinalitykit

From Source

# Clone the repository
git clone https://github.com/GiacomoSaccaggi/CardinalityKit.git
cd CardinalityKit

# Install the package in development mode
pip install -e .

Requirements

  • Python 3.7+
  • numpy >= 1.19.0
  • pandas >= 1.1.0
  • tqdm >= 4.50.0
  • scipy >= 1.5.0

Quick Start

Basic Usage: Estimate Unique Count

from cardinalitykit import HyperLogLogEstimator
import hashlib

# Create estimator with k=10 (1024 buckets)
hll = HyperLogLogEstimator(k=10)

# Process your data
data = ["user_1", "user_2", "user_3", "user_1"]  # user_1 appears twice

for item in data:
    # Hash the item to binary
    hash_val = '{:32b}'.format(int(hashlib.sha256(item.encode()).hexdigest()[:8], 16))
    hll.update(hash_val)

# Get estimate
estimate = hll.estimate()
print(f"Estimated unique count: {estimate:.0f}")  # Output: ~3
print(f"Memory used: {hll.memory_usage()} bytes")  # Output: 1024 bytes

Track Demographics with Extended Algorithms

from cardinalitykit import ExtendedHyperLogLogSketch

# Create extended sketch
ehll = ExtendedHyperLogLogSketch(b_m=8, b_s=8)

# Process events with attributes
events = [
    {'id_to_count': 'user_1', 'attribute': 'age_18_24'},
    {'id_to_count': 'user_2', 'attribute': 'age_25_34'},
    {'id_to_count': 'user_3', 'attribute': 'age_18_24'},
]

for event in events:
    ehll.update_sketch(event)

# Get total and per-attribute estimates
total = ehll.get_cardinality_estimate()
by_age = ehll.get_frequency_for_attr()

print(f"Total unique users: {total:.0f}")
print(f"By age group: {by_age}")

Convert Sample Data to Population Estimates

from cardinalitykit import ExtendedHyperRealSketchFromSample

# Sample data: (id, weight, attribute)
sample_data = [
    ("panelist_1", 0.4, "demographic_A"),
    ("panelist_2", 0.6, "demographic_B")
]

# Create converter
converter = ExtendedHyperRealSketchFromSample(b_m=8, sample_data=sample_data)

# Run association (choose naive or fast)
converter.naive_associate(sum_weights=10000)
# OR for better performance:
# converter.fast_associate(sum_weights=10000, D=100)

# Get population estimates
estimate = converter.get_cardinality_estimate()
attr_freq = converter.get_frequency_for_attr()

print(f"Estimated population: {estimate:.0f}")
print(f"By demographic: {attr_freq}")

Algorithm Comparison

Algorithm Memory Accuracy Error Rate Use Case
Flajolet-Martin Low Basic ~30% Historical reference
LogLog Medium Good ~5% General purpose
SuperLogLog Medium Better ~3% Outlier elimination
HyperLogLog Medium Best ~1.04/√m Industry standard
HyperReal Medium Excellent Unbiased Research/high precision

Error rates are approximate and depend on the number of buckets (m = 2^k)

Configuration

Precision Parameter (k)

The k parameter controls the number of buckets (m = 2^k) and affects accuracy vs memory:

# Low memory, lower accuracy (~3.2% error)
hll = HyperLogLogEstimator(k=10)  # 1 KB

# Balanced (recommended)
hll = HyperLogLogEstimator(k=14)  # 16 KB, ~0.8% error

# High accuracy (~0.4% error)
hll = HyperLogLogEstimator(k=16)  # 64 KB

Standard error formula: 1.04 / sqrt(2^k)

Examples

Run the included examples:

python -m cardinalitykit.examples

Or run specific examples:

from cardinalitykit.examples import *

basic_example()              # Basic HyperLogLog usage
comparison_example()         # Compare all algorithms
extended_example()           # Extended algorithms with attributes
sample_conversion_example()  # Sample data conversion

Use Cases

1. Privacy-Preserving Analytics

Estimate unique visitors without storing user IDs:

# Process millions of user IDs
for user_id in user_stream:
    hash_val = hash_function(user_id)
    hll.update(hash_val)

# Get estimate without exposing individual users
unique_visitors = hll.estimate()

2. Cross-Platform Deduplication

Combine sketches from different platforms:

# Each platform creates its own sketch
mobile_hll = HyperLogLogEstimator(k=14)
web_hll = HyperLogLogEstimator(k=14)

# Merge sketches (implementation in extended algorithms)
# Get deduplicated total reach

3. Real-Time Monitoring

Stream processing with constant memory:

# Memory usage stays constant regardless of stream size
for event in infinite_stream:
    hll.update(hash_function(event.user_id))
    if event.timestamp % 1000 == 0:
        print(f"Current unique users: {hll.estimate():.0f}")

Documentation

Full documentation available in the documentation/ folder:

Development

Running Simulations

# Compare all algorithms
cd simulation/Simulation\ of\ the\ various\ algorithms/
python main.py

# HyperLogLog vs HyperReal comparison
cd simulation/HLL\ vs\ HR/
python main_HLL_vs_HR.py

# Sample conversion experiments
cd simulation/From\ Sample\ to\ Hr/
python From_Sample_to_HR_Fast_Association.py

Testing

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run with coverage
pytest --cov=cardinalitykit --cov-report=html

Performance

  • Update: O(1) - constant time per element
  • Estimate: O(m) - linear in number of buckets
  • Memory: O(m) - fixed regardless of input size
  • Streaming: Supports unlimited input size

License

MIT License - See LICENSE file for details

References

  • Flajolet, P., & Martin, G. N. (1985). "Probabilistic counting algorithms for data base applications"
  • Durand, M., & Flajolet, P. (2003). "Loglog counting of large cardinalities"
  • Flajolet, P., et al. (2007). "HyperLogLog: the analysis of a near-optimal cardinality estimation algorithm"

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Author

Giacomo Saccaggi — GitHub

Support

For questions and issues, please open an issue on GitHub.

Metadata

Release files for cardinalitykit 1.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cardinalitykit 1.0.2
File Size Uploaded
cardinalitykit-1.0.2.tar.gz 75.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cardinalitykit 1.0.2
File Interpreter ABI Platform
cardinalitykit-1.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 94.5 kB

Release files / cardinalitykit-1.0.2.tar.gz

Download URL cardinalitykit-1.0.2.tar.gz
Size 75.1 kB
Tags Source
SHA-256 checksum
How to use checksums
6ae7da656ceaf4ee1d4a90f79f16da916413338dbcada664381f21bf58d80ad4
BLAKE2b-256 checksum
How to use checksums
685f56765eb1401befb0bdc2e391a0c1b9e85d1211061348d40cbcc85bcba7d6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.11

Release files / cardinalitykit-1.0.2-py3-none-any.whl

Download URL cardinalitykit-1.0.2-py3-none-any.whl
Size 19.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
53737907dd21d83dd8003c9430da959b852d0bdf77bb6972ceaac1451bc3febc
BLAKE2b-256 checksum
How to use checksums
6e8ea31e1e878bfb9e5c2fe3f92534266412b795bf022f4ad111f8858c708b87
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.11

Release history Release notifications | RSS feed

This release

1.0.2 This release

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page