Modern Spark distribution fitting library with efficient parallel processing
Efficiently fit ~100 scipy.stats distributions to your data using Spark's parallel processing with optimized Pandas UDFs and broadcast variables.
- Parallel Processing: Fits distributions in parallel using Spark
- ~100 Distributions: Access to nearly all scipy.stats continuous distributions
- Histogram-Based Fitting: Efficient fitting using histogram representation
- Multiple Metrics: Compare fits using K-S statistic (default), SSE, AIC, and BIC
- Statistical Validation: Kolmogorov-Smirnov test with p-values for goodness-of-fit
- Results API: Filter, sort, and export results easily
- Visualization: Built-in plotting for distribution comparison and Q-Q plots
- Flexible Configuration: Customize bins, sampling, and distribution selection
pip install spark-bestfitfrom spark_bestfit import DistributionFitter
import numpy as np
from pyspark.sql import SparkSession
spark = SparkSession.builder.getOrCreate()
# Generate sample data
data = np.random.normal(loc=50, scale=10, size=10_000)
# Create fitter
fitter = DistributionFitter(spark)
df = spark.createDataFrame([(float(x),) for x in data], ["value"])
# Fit distributions
results = fitter.fit(df, column="value")
# Get best fit (by K-S statistic, the default)
best = results.best(n=1)[0]
print(f"Best: {best.distribution} (KS={best.ks_statistic:.4f}, p={best.pvalue:.4f})")
# Plot
fitter.plot(best, df, "value", title="Best Fit Distribution")| Spark Version | Python Versions | NumPy | Pandas | PyArrow |
|---|---|---|---|---|
| 3.5.x | 3.11, 3.12 | 1.24+ (< 2.0) | 1.5+ | 12.0 - 16.x |
| 4.0.x | 3.12, 3.13 | 2.0+ | 2.2+ | 17.0+ |
Note: Spark 3.5.x does not support NumPy 2.0. If using Spark 3.5 with Python 3.12, ensure
setuptoolsis installed (providesdistutils).
from spark_bestfit import DistributionFitter
fitter = DistributionFitter(spark, random_seed=123)
results = fitter.fit(
df,
column="value",
bins=100, # Number of histogram bins
support_at_zero=True, # Only fit non-negative distributions
enable_sampling=True, # Enable adaptive sampling
sample_fraction=0.3, # Sample 30% of data
max_distributions=50, # Limit distributions to fit
)# Get top 5 distributions (by K-S statistic, the default)
top_5 = results.best(n=5)
# Get best by other metrics
best_sse = results.best(n=1, metric="sse")[0]
best_aic = results.best(n=1, metric="aic")[0]
# Filter by goodness-of-fit
good_fits = results.filter(ks_threshold=0.05) # K-S statistic < 0.05
significant = results.filter(pvalue_threshold=0.05) # p-value > 0.05
# Convert to pandas for analysis
df_pandas = results.df.toPandas()
# Use fitted distribution
samples = best.sample(size=10000) # Generate samples
pdf_values = best.pdf(x_array) # Evaluate PDF
cdf_values = best.cdf(x_array) # Evaluate CDFfitter.plot(
best,
df,
"value",
figsize=(16, 10),
dpi=300,
histogram_alpha=0.6,
pdf_linewidth=3,
title="Distribution Fit",
xlabel="Value",
ylabel="Density",
save_path="output/distribution.png",
)# Create Q-Q plot for goodness-of-fit assessment
fitter.plot_qq(
best,
df,
"value",
max_points=1000, # Sample size for plotting
title="Q-Q Plot",
save_path="output/qq_plot.png",
)from spark_bestfit import DistributionFitter, DEFAULT_EXCLUDED_DISTRIBUTIONS
# View default exclusions
print(DEFAULT_EXCLUDED_DISTRIBUTIONS)
# Include a specific distribution by removing it from exclusions
exclusions = tuple(d for d in DEFAULT_EXCLUDED_DISTRIBUTIONS if d != "wald")
fitter = DistributionFitter(spark, excluded_distributions=exclusions)
# Or exclude nothing (fit all distributions - may be slow)
fitter = DistributionFitter(spark, excluded_distributions=())Full documentation is available at spark-bestfit.readthedocs.io.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feat/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feat/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.