Skip to main content

Statistics Operations

The iterable.ops.stats module provides functions for computing statistics, frequency analysis, and unique value detection on datasets.

Overview

Statistics operations help you understand data distributions and patterns:

  • Compute comprehensive statistics for all fields
  • Analyze frequency distributions of values
  • Detect unique values and duplicates
  • Leverage DuckDB for fast computation on large datasets

Functions

compute()

Compute comprehensive statistics for all fields in an iterable dataset.

from iterable.ops import stats

# Compute statistics for a file
summary = stats.compute("data.csv", detect_dates=True)
print(summary["price"]["mean"])
print(summary["price"]["stddev"])

# Compute statistics for an iterable
rows = [
{"value": 1, "name": "a"},
{"value": 2, "name": "b"},
{"value": 3, "name": "c"},
]
summary = stats.compute(rows)

Parameters:

  • iterable: An iterable of row dictionaries, or a file path/stream
  • detect_dates: Whether to detect date fields (default: False)
  • engine: Optional engine to use ('duckdb' for optimization)
  • include_top_values: When True, include top_values (most frequent values with counts) per field (default: False)
  • top_n: Number of top values to include when include_top_values is True (default: 10)
  • dict_threshold: Unique-to-total ratio at/below which a field is flagged as a dictionary (lookup) field. Defaults to the DICT_THRESHOLD environment variable or 0.1.

Returns: Dictionary mapping field names to their statistics:

  • count: Number of non-null values
  • null_count: Number of null values
  • null_fraction: Fraction of values that are null (0..1)
  • unique_count: Number of unique values
  • is_dictionary: Whether the field behaves as a dictionary/lookup field
  • top_values: List of {value, count} (only when include_top_values=True)
  • min, max: Minimum and maximum values (for numeric fields)
  • mean, median, stddev: Statistical measures (for numeric fields)
  • min_length, max_length, avg_length: String length statistics (for string fields)

Example Output:

{
"price": {
"count": 1000,
"null_count": 5,
"unique_count": 250,
"min": 10.0,
"max": 999.99,
"mean": 245.5,
"median": 200.0,
"stddev": 150.2
},
"name": {
"count": 1000,
"null_count": 0,
"unique_count": 500,
"min_length": 3,
"max_length": 50,
"avg_length": 12.5
}
}

frequency()

Compute frequency distributions for specified fields.

from iterable.ops import stats

# Frequency analysis for single field
freq = stats.frequency("data.csv", fields=["status"])
print(freq["status"]["active"]) # Count of "active" status

# Frequency analysis for multiple fields
freq = stats.frequency("data.csv", fields=["status", "category"])

# Frequency with limit (top N most frequent)
freq = stats.frequency("data.csv", fields=["status"], limit=10)

Parameters:

  • iterable: An iterable of row dictionaries, or a file path/stream
  • fields: List of field names to analyze (None for all fields)
  • limit: Optional limit on number of top frequencies to return per field

Returns: Dictionary mapping field names to frequency dictionaries (value -> count, sorted by frequency descending)

Example Output:

{
"status": {
"active": 750,
"inactive": 200,
"pending": 50
},
"category": {
"A": 400,
"B": 300,
"C": 300
}
}

uniq()

Identify unique rows or unique values for specified fields.

from iterable.ops import stats

# Get unique rows by email
unique_rows = list(stats.uniq("data.csv", fields=["email"]))

# Get unique values only
unique_emails = list(stats.uniq("data.csv", fields=["email"], values_only=True))

# Get unique values with counts
counts = stats.uniq("data.csv", fields=["email"], include_count=True)
print(counts["user@example.com"]) # Count of occurrences

Parameters:

  • iterable: An iterable of row dictionaries, or a file path/stream
  • fields: List of field names to use for uniqueness (None for all fields)
  • values_only: If True, return only unique values (not full rows)
  • include_count: If True, include occurrence counts in results

Returns:

  • If values_only=True: Iterator of unique values
  • If include_count=True: Dictionary mapping unique items to counts
  • Otherwise: Iterator of unique rows

Examples

Basic Statistics

from iterable.ops import stats

# Compute statistics for all fields
summary = stats.compute("sales.csv", detect_dates=True)

# Access statistics for a field
price_stats = summary["price"]
print(f"Price range: ${price_stats['min']:.2f} - ${price_stats['max']:.2f}")
print(f"Average price: ${price_stats['mean']:.2f}")
print(f"Standard deviation: ${price_stats['stddev']:.2f}")
print(f"Unique prices: {price_stats['unique_count']}")

Frequency Analysis

from iterable.ops import stats

# Find most common status values
freq = stats.frequency("users.csv", fields=["status"], limit=5)

print("Top 5 statuses:")
for status, count in freq["status"].items():
print(f" {status}: {count}")

# Analyze multiple fields
freq = stats.frequency("products.csv", fields=["category", "brand"])
for field, frequencies in freq.items():
print(f"\n{field} distribution:")
for value, count in list(frequencies.items())[:5]: # Top 5
print(f" {value}: {count}")

Finding Duplicates

from iterable.ops import stats

# Find unique emails
unique_emails = list(stats.uniq("users.csv", fields=["email"], values_only=True))
print(f"Unique emails: {len(unique_emails)}")

# Find duplicate emails with counts
email_counts = stats.uniq("users.csv", fields=["email"], include_count=True)
duplicates = {email: count for email, count in email_counts.items() if count > 1}
print(f"Duplicate emails: {len(duplicates)}")
for email, count in duplicates.items():
print(f" {email}: {count} occurrences")

Data Quality Analysis

from iterable.ops import stats

# Analyze data quality
summary = stats.compute("data.csv")

for field, stats_info in summary.items():
null_pct = (stats_info["null_count"] /
(stats_info["count"] + stats_info["null_count"]) * 100)

print(f"{field}:")
print(f" Null percentage: {null_pct:.1f}%")
print(f" Unique values: {stats_info['unique_count']}")

if "mean" in stats_info:
print(f" Range: {stats_info['min']} - {stats_info['max']}")
print(f" Mean: {stats_info['mean']:.2f}")

Combining with Other Operations

from iterable.ops import inspect, stats, transform

# Analyze a sample of data
sample = list(transform.sample_rows("large_dataset.csv", n=10000))
summary = stats.compute(sample)

# Get frequency of top categories
freq = stats.frequency(sample, fields=["category"], limit=10)

# Find unique combinations
unique = list(stats.uniq(sample, fields=["user_id", "product_id"]))
print(f"Unique user-product combinations: {len(unique)}")

Performance Notes

  • compute(): For large files, consider using engine="duckdb" for significant performance improvements
  • frequency(): Efficient streaming implementation, handles large datasets well
  • uniq(): Memory-efficient for unique value detection, but may require full iteration

Integration with DuckDB

When available, DuckDB can significantly speed up statistics computation:

from iterable.ops import stats

# Fast statistics with DuckDB (for CSV/JSONL/JSON/Parquet)
try:
summary = stats.compute("large_file.csv", engine="duckdb")
except Exception:
# Falls back to Python implementation
summary = stats.compute("large_file.csv")

Type Detection

The compute() function automatically detects field types:

  • Numeric fields: Get min, max, mean, median, stddev
  • String fields: Get min_length, max_length, avg_length
  • Date fields: Enable with detect_dates=True for date-specific statistics