👇 连享会 · 推文导航 | www.lianxh.cn
连享会:2026暑期班 · 线上
时间:7月21-31日
嘉宾:连玉君(初级班) || 茅家铭(高级班) || 范馨月(论文班)
咨询:王老师 18903405450(微信)

本次暑期班围绕实证研究能力的三层递进展开:
公开课,扫码进群即可参加


温馨提示: 文中链接在微信中无法生效。请点击底部「阅读原文」。或直接长按/扫描如下二维码,直达原文:
作者: 张祖冲(江苏大学)
邮箱: zzchong1228@163.com
distfit | HomePage | Source Code - Github | Example Notebooks | Documentation
1. 引言
在数据科学领域,理解数据集的底层概率分布是执行假设检验、构建模拟模型和进行异常检测等关键任务的基石。传统上,Python 数据科学家依赖于功能强大的scipy.stats库来执行分布拟合。这个过程虽然稳健,但通常是手动的、重复的。我们需要首先对可能适合数据的候选分布有一个初步的假设,然后编写代码,对每个候选分布进行单独拟合,计算拟合优度(Goodness-of-Fit, GOF)指标,最后比较这些指标以确定最佳模型。
scipy.stats.fit函数是这一过程的核心构建块,但它要求用户预先指定要拟合的分布对象。这引出了一个核心的“发现问题”:如果我们不确定哪些分布是合适的候选者,或者希望探索更广泛的可能性,该怎么办?手动测试数十种分布不仅效率低下,而且容易出错,需要大量的样板代码来管理循环、结果存储和错误处理。这种方法限制了分析的广度和深度,可能会导致我们仅仅依赖于少数几种熟悉的分布(如正态分布),从而错失更精确描述数据的模型。
2. Python 扩展包:distfit
distfit 的出现正是为了解决上述挑战。它是一个专为单变量随机变量进行概率密度拟合而设计的 Python 包,其核心价值在于自动化。distfit 能够将经验数据与源自scipy 库的超过 89 种理论分布进行自动测试,从而找到最佳拟合模型。
2.1 简介
该库的强大之处在于其「端到端」的解决方案。用户只需提供原始数据,distfit 就能自动完成整个发现、拟合、评估和可视化的流程,最终返回最佳拟合分布的名称及其关键参数(如loc、
scale 和 arg)。此外,distfit 的功能覆盖范围极广,它不仅支持参数化拟合,还提供了非参数化和离散的拟合方法,并内置了预测、数据生成等实用功能,使其成为一个适用于多种数据类型和应用场景的综合性工具。
2.2 安装与设置
distfit 的安装过程非常直接,可以通过 Python 的包管理器 pip 轻松完成。
pip install distfit
# 如果运行失败,可能是因为distfit对scipy的版本有要求,可尝试以下命令
pip install --upgrade statsmodels
pip install "scipy<1.13"
distfit 依赖于数据科学生态中常见的库,如numpy、
pandas和matplotlib,这些通常已经存在于标准的分析环境中。
3. 核心功能:选择拟合方法
distfit 提供了多种拟合方法,以适应不同类型的数据和分析需求。
3.1 参数化拟合 (Parametric Fitting)
参数化拟合是 distfit 最核心和最常用的功能。它指的是用一组具有已知数学形式的理论分布(由参数定义,如正态分布的均值和标准差)来拟合经验数据。当 fit_transform(X) 被调用时,distfit 会遍历其内部包含的众多理论分布,将每一种分布与输入数据 X 进行拟合,并找到最佳模型。
3.1.1 指定要测试的分布
distfit 允许用户通过 distr 参数灵活地指定要测试的分布范围,这对于提高效率和引入先验知识至关重要。
手动指定分布
当您对数据可能遵循的分布有初步判断时,可以手动指定一个或多个分布进行测试,以节省计算时间。
代码示例:仅测试正态分布和t分布
import numpy as np
from distfit import distfit
import matplotlib.pyplot as plt
# 1. 生成近似正态分布的数据
X = np.random.normal(loc=10, scale=3, size=1000)
# 2. 初始化 distfit,仅测试 'norm' 和 't' 分布
dfit = distfit(distr=['norm', 't'])
# 3. 执行拟合
dfit.fit_transform(X)
# 4. 打印最佳模型
print(dfit.model)
# 5. 可视化拟合结果
dfit.plot()
plt.title("拟合正态分布和t分布")
plt.show()
20250818231651使用 'popular' 集合
这是一个包含 10 个常用分布的预设集合,是在不确定具体分布时的理想起点。
代码示例:使用 'popular' 集合拟合 Gamma 数据
import numpy as np
from distfit import distfit
import matplotlib.pyplot as plt
# 1. 生成符合 Gamma 分布的示例数据
X = np.random.gamma(shape=2., scale=2., size=1000)
# 2. 初始化 distfit,并选择 "popular" 集合进行测试
dfit = distfit(distr='popular')
# 3. 执行拟合
dfit.fit_transform(X)
# 4. 打印最佳拟合模型(应为 gamma)
print(dfit.model)
# 5. 可视化拟合结果
dfit.plot(n_top=3) # 绘制最佳的3个拟合
plt.title("使用 'popular' 集合进行拟合")
plt.show()
20250818231706使用 'full' 集合
该选项会测试 distfit 支持的所有(近 89 种)分布。这在进行探索性分析时非常有用,但请注意,对于大型数据集,这可能会非常耗时。
注意:levy_l, levy_stable,
frechet_r, 和 frechet_l 因性能或兼容性问题可能已被移除。
代码示例:使用 'full' 集合进行拟合
import numpy as np
from distfit import distfit
import matplotlib.pyplot as plt
# 1. 生成对数正态分布数据
X = np.random.lognormal(mean=2, sigma=0.5, size=1000)
# 2. 初始化 distfit,选择所有支持的分布进行测试
# 警告:这可能会花费一些时间
dfit = distfit(distr='full')
# 3. 执行拟合
dfit.fit_transform(X)
# 4. 打印最佳拟合模型
print(dfit.model)
# 5. 可视化最佳拟合结果
dfit.plot()
plt.title("使用 'full' 集合进行拟合")
plt.show()
202508182317203.1.2 拟合优度评估
distfit 通过计算观测频率与模型预测频率之间的差异来评估拟合的好坏。
残差平方和 (Residual Sum of Squares, RSS)
默认情况下,distfit 使用残差平方和(RSS)作为评估指标。RSS 衡量的是数据与估计模型之间的差异。一个小的 RSS 值表示模型对数据的拟合非常紧密。其计算公式为:
其中, 是变量的第 i 个观测值, 是 的预测值(也称为 )。
其他评分选项
除了 RSS,distfit 还支持多种其他的拟合优度检验统计量,可以通过 stats 参数进行选择。
| |
|---|
RSS | 观测值与估计的概率密度函数(PDF)之间的残差平方和。 |
wasserstein | |
ks | 用于比较经验累积分布函数(CDF)的柯尔莫哥洛夫-斯米尔诺夫检验统计量。 |
energy | |
goodness_of_fit | 来自 scipy.stats.goodness_of_fit 的通用检验,包括 Cramér–von Mises 和 Anderson–Darling 统计量。 |
3.2 非参数化拟合 (Quantile Fitting)
当数据的底层分布不遵循任何特定的数学形式,或呈现多峰等复杂形态时,参数化方法可能不适用。此时,可以使用非参数化的分位数(quantile)方法。它不依赖于理论分布,而是直接基于数据的分位数来计算置信区间。
代码示例:
import numpy as np
from distfit import distfit
import matplotlib.pyplot as plt
# 1. 生成双峰分布数据,这种数据很难用单一的参数分布来拟合
X1 = np.random.normal(loc=-2, scale=1, size=500)
X2 = np.random.normal(loc=5, scale=1.5, size=500)
X = np.concatenate([X1, X2])
# 2. 初始化 distfit 对象,并指定使用分位数方法
dfit = distfit(method='quantile')
# 3. 对数据进行非参数化拟合
dfit.fit_transform(X)
# 4. 查看基于分位数的置信区间
print(f"置信区间下界: {dfit.model['CII_min_alpha']}")
# > 置信区间下界: -3.89...
print(f"置信区间上界: {dfit.model['CII_max_alpha']}")
# > 置信区间上界: 7.23...
# 5. 可视化拟合结果
dfit.plot()
plt.title('非参数化拟合 (双峰分布)')
plt.show()
20250818231759# 6. 对新数据点进行预测
y = [-5, 0, 8]
dfit.predict(y)
dfit.plot() # 绘制带有预测点的图
plt.title('非参数化拟合及预测')
plt.show()
20250818231810当你的数据分布复杂,例如,呈现双峰或严重偏态,无法用任何标准参数分布很好地拟合时,这种非参数化方法是确保分析严谨性的关键。基于分位数的非参数化方法稳健地估计其95%置信区间,并以此为基准进行后续的离群点识别,从而避免了模型错配可能带来的偏见。
3.3 离散分布拟合 (Discrete Fitting)
当处理的数据是离散的整数(如计数)时,应使用离散概率分布进行拟合。distfit 的 discrete 方法主要使用二项分布来寻找最佳拟合。给定一组非负整数,它会尝试找到最佳的 n(试验次数)和 p(成功概率)组合。
代码示例:
import numpy as np
from distfit import distfit
import matplotlib.pyplot as plt
from scipy.stats import binom
# 1. 生成符合二项分布的示例数据
# 例如,模拟抛硬币 8 次,正面朝上的次数,重复 10000 次
n, p = 8, 0.5
X = binom(n, p).rvs(10000)
# 2. 初始化 distfit 对象,并指定为离散数据拟合
dfit = distfit(method='discrete')
# 3. 执行离散拟合
# [distfit] >fit..
# [distfit] >transform..
# [distfit] >Fit using binomial distribution..
# [distfit] >[binomial] [SSE: 7.79] [n: 8] [p: 0.499959] [chi^2: 1.11]
# [distfit] >Compute confidence interval [discrete]
dfit.fit_transform(X)
# 4. 打印最佳拟合参数
# 结果表明,模型成功地找回了原始参数 n=8 和 p≈0.5
print("离散拟合 (二项分布) 模型:")
print(dfit.model)
# {'model': <...>, 'params': (8, 0.499...), 'name': 'binom', ...}
# 5. 可视化拟合结果
dfit.plot()
plt.title('离散拟合 (二项分布)')
plt.show()
20250818231823# 6. 对新数据点进行预测
y = [0, 1, 10, 11, 12] # 包含正常值和极端值
results = dfit.predict(y)
dfit.plot() # 绘制带有预测结果的图
plt.title('离散拟合及预测')
plt.show()
20250818231833
对于计数类型的数据(例如,单位面积内的细胞数量、特定时间窗口内的事件发生次数、基因测序读数),采用离散分布进行建模是标准且正确的研究方法。
4. 结果的解读与可视化
完成拟合后,distfit 提供了丰富的属性和方法来检查、比较和可视化结果。
4.1 访问拟合结果
- 最佳模型 (
dfit.model):一个字典,包含最佳拟合分布的详细信息,如名称 (name)、参数 (params)、RSS分数 (RSS) 等。 - 所有模型摘要 (
dfit.summary):一个 Pandas DataFrame,列出了所有已测试分布及其对应的 RSS 分数,方便进行全面比较。 - 分布对象 (
dfit.distributions):从 scipy 提取的、用于测试的分布对象列表。
代码示例:
import numpy as np
from distfit import distfit
# 1. 生成数据并拟合
X = np.random.gamma(shape=2., scale=2., size=1000)
dist = distfit(distr=['norm', 'gamma', 'lognorm', 'beta'])
dist.fit_transform(X)
# 2. 打印最佳模型的详细信息
print("最佳拟合模型信息:")
print(dist.model)
# 3. 打印所有已测试分布的摘要
print("\n所有已测试分布的拟合摘要:")
print(dist.summary)
4.2 可视化工具
distfit 强大的可视化功能是其一大亮点,可以帮助用户直观地评估拟合质量。
4.2.1 基础 PDF/CDF 图 (plot)
plot 方法是核心的可视化工具,可以绘制概率密度函数(PDF)或累积分布函数(CDF)。
import numpy as np
from distfit import distfit
import matplotlib.pyplot as plt
# 1. 创建数据集
X = np.random.normal(0, 2,
10000)
# 2. 初始化并拟合
dfit = distfit()
dfit.fit_transform(X)
# 3. 分别绘制 PDF 和 CDF 图
fig1, ax1 = dfit.plot(chart='pdf')
ax1.set_title('概率密度函数 (PDF)')
plt.show()
20250818231852fig2, ax2 = dfit.plot(chart='cdf')
ax2.set_title('累积分布函数 (CDF)')
plt.show()
20250818231906# 4. 将多个拟合分布绘制在同一张图上
fig3, ax3 = dfit.plot(chart='pdf', n_top=5) # 绘制拟合最好的前 5 个分布
ax3.set_title('多个拟合分布的 PDF')
plt.show()
20250818231919# 5. 自由定制图表元素
dfit.plot(chart='pdf',
pdf_properties={'color': 'r', 'linewidth'
: 3}, # PDF 线条
cii_properties={'color': 'g', 'linestyle': '--'}, # 置信区间线条
bar_properties=None, # 移除直方图条
emp_properties={'color': 'purple', 'linewidth': 2}) # 经验分布线条
plt.title('自定义样式的 PDF 图')
plt.show()
202508182319294.2.2 拟合摘要图 (plot_summary)
该方法将 dfit.summary 的内容可视化,直观地比较所有测试分布的拟合优度分数。
import numpy as np
from distfit import distfit
import matplotlib.pyplot as plt
# 1. 生成数据并拟合
X = np.random.gamma(shape=2., scale=2., size=1000)
dist = distfit(distr=['norm', 'gamma', 'lognorm', 'beta'])
dist.fit_transform(X)
# 2. 绘制摘要图
dist.plot_summary()
plt.title('模型摘要图')
plt.show()
202508182319414.2.3 Q-Q 图 (qqplot)
Q-Q 图(Quantile-Quantile Plot)用于视觉上检验拟合分布与经验数据的吻合程度。如果图上的点大致落在对角线上,说明拟合效果很好。
import numpy as np
from distfit import distfit
import matplotlib.pyplot as plt
# 1. 生成数据并拟合
X = np.random.gamma(shape=2., scale=2., size=1000)
dist = distfit(distr=['norm', 'gamma', 'lognorm', 'beta'])
dist.fit_transform(X)
# 2. 绘制Q-Q图
dist.qqplot()
plt.title('Q-Q 图')
plt.show()
20250818231952
5. 应用场景
distfit 不仅能找到最佳分布,还提供了基于该分布的实用功能。
5.1 预测与异常检测 (predict)
predict(y) 方法是 distfit 的一个关键功能。它基于拟合好的最佳分布,计算一组新数据点 y 出现的概率,这在异常检测中极为有用。
多重检验校正
一个值得称赞的特性是,distfit 在计算概率时默认执行了多重检验校正(默认方法为 Benjamini/Hochberg fdr_bh),这对于在同时检验多个数据点时控制伪发现率(False Discovery Rate)至关重要。可以通过 multtest 参数在初始化时更改校正方法。
multtest | |
None | |
bonferroni | |
sidak | |
holm-sidak | step down method using Sidak adjustments |
holm | step-down method using Bonferroni adjustments |
simes-hochberg | step-up method (independent) |
hommel | closed method based on Simes tests (non-negative) |
fdr_bh | Benjamini/Hochberg (non-negative) |
fdr_by | Benjamini/Yekutieli (negative) |
fdr_tsbh | two stage fdr correction (non-negative) |
fdr_tsbky | two stage fdr correction (non-negative) |
代码示例
import numpy as np
from distfit import distfit
import matplotlib.pyplot as plt
# 1. 生成正态分布数据并进行拟合
X = np.random.normal(loc=10, scale=3, size=1000)
dist = distfit(todf=True) # 使用 todf=True 方便结果以 DataFrame 形式查看
dist.fit_transform(X)
# 2. 定义一组待测数据,包含正常值、边界值和极端值
y = np.array([9, 11, 1, 20, 25])
# 3. 进行预测
dist.predict(y)
# 4. 打印预测结果
# 'y_proba' 是校正后的p值,值越小,说明该数据点越“异常”
# 'y_pred' 直接给出了判断:'up' (显著高), 'down' (显著低), 'none' (正常)
print(f"基于拟合模型 ({dist.model['name']}) 的预测结果:")
print(dist.results['df'])
# 5. 可视化预测结果
dist.plot()
plt.title(f"预测点在 {dist.model['name']} 分布上的位置")
plt.show()
20250818232011对于需要从大量数据中客观识别显著信号或异常样本的研究,本方法至关重要。为了从实验组数据中识别出与对照组相比表现异常的样本,首先使用对照组数据建立一个基线分布模型。随后,我们利用该模型的predict功能,计算实验组中每个数据点的p值。考虑到多重比较问题,我们采用Benjamini-Hochberg程序对p值进行校正,以控制伪发现率(FDR)。FDR小于0.05的样本被定义为统计学上显著的离群点。
5.2 生成合成数据 (generate)
distfit 的另一个实用功能是 generate(n) 方法,它允许用户从最佳拟合分布中生成新的随机样本。这个功能完成了从“分析数据”到“利用模型”的闭环,应用场景非常广泛,包括:
代码示例:
import numpy as np
from distfit import distfit
import matplotlib.pyplot as plt
# 1. 假设我们有一组真实数据,并对其进行拟合
X_real = np.random.lognormal(mean=2, sigma=0.5, size=1000)
dist = distfit()
dist.fit_transform(X_real)
print(f"找到的最佳拟合分布为: {dist.model['name']}")
# 2. 使用 generate 方法生成 1000 个新的合成数据点
X_synthetic = dist.generate(n=1000)
# 3. 可视化对比真实数据和合成数据
plt.figure(figsize=(10, 6))
plt.hist(X_real, bins=50, density=True, alpha=0.6, label='真实数据')
plt.hist(X_synthetic, bins=50, density=True, alpha=0.6, label='合成数据')
plt.title('真实数据与合成数据的分布对比')
plt.legend()
plt.show()
20250818232022当真实实验数据量有限,但研究需要进行大规模模拟或模型验证时,此功能尤为强大。通过distfit对现有真实变量数据进行分布拟合,确定其最佳拟合模型分布。为了进行稳健的蒙特卡洛模拟,我们可以利用该模型的generate功能生成一个包含100,000个数据点的合成数据集。该数据集在均值、方差等关键统计特性上与真实数据高度一致,确保了我们后续模型的有效性和可靠性。
5.3 使用自举法 (Bootstrapping) 验证模型稳定性
仅仅找到当前数据集上的“最佳”拟合分布有时是不够的。一个稳健的模型应该在其数据的微小变动下依然表现出色。自举法(Bootstrapping)通过对原始数据进行有放回的重采样来模拟这种变动,从而检验拟合模型的稳定性。在 distfit 中,只需在初始化时设置 n_boots 参数即可激活此功能。
import numpy as np
from distfit import distfit
import matplotlib.pyplot as plt
# 1. 生成数据
X = np.random.normal(163, 10, 10000)
# 2. 初始化时启用100次自举重采样
dfit = distfit(distr='popular', n_boots=100)
# 3. 执行拟合与验证
results = dfit.fit_transform(X)
# 4. 查看带有自举结果的摘要
# 新增了 'bootstrap_score' 和 'bootstrap_pass' 两列
print(dfit.summary[['name', 'score', 'bootstrap_score', 'bootstrap_pass']])
# 5. 可视化原始数据的拟合摘要
dfit.plot_summary()
plt.show()
20250818232033执行自举后,summary 表中会新增两列:
bootstrap_score: 分布在所有自举样本上的平均 RSS 分数,提供更稳健的性能评估。bootstrap_pass: 指示该分布是否在多数自举样本中保持最佳(稳健性通过)。
理想模型应兼具较低的 score 与 bootstrap_score,且 bootstrap_pass 为 True,表明其优越性并非偶然。
为验证所选分布模型的稳健性与泛化能力,避免其成为特定样本的偶然拟合结果,我们可以实施自举法进行验证。通过对原始数据集进行100次有放回的重采样,生成一系列与原始数据略有差异的子数据集。随后,候选分布模型将在每个子数据集上重新进行拟合与评估。一个在原始数据上表现最优,并且在绝大多数自举样本中依然保持其优越性的模型,被认为是稳定且可靠的。此验证步骤确保了我们所选模型的有效性并非源于抽样偏差,从而为所有基于该模型的后续统计推断提供了更为坚实的依据。
6. 灵活性与性能优化
distfit 在提供自动化便利的同时,也保留了高度的灵活性和控制权。用户可以通过在初始化时设置不同的参数来定制其行为。
| | | |
|---|
method | | 'parametric' | 指定拟合方法: 'parametric', 'quantile', 'discrete' |
alpha | | 0.05 | |
multtest |
| 'fdr_bh' | |
bins | | 50 | |
bound | | 'both' | 检验显著性的方向性: 'both', 'up', 'down'。 |
distr | |
'popular' | |
stats | | 'RSS' | |
n_jobs | | None | 并行计算使用的 CPU 核心数 (-1 表示使用所有核心)。 |
n_perm | | 10000 | 在 method='empirical' 中用于建模空分布的置换次数。 |
n_boots | | 0 | |
7. 总结
distfit 不仅仅是一个理论拟合工具,更是一个面向实际应用的解决方案。它将分布发现、参数估计、结果可视化、异常检测和数据模拟等多个环节无缝集成到一个统一且简洁的框架内。我们无需再为了拟合、预测和生成数据而拼凑多个不同的库,从而可以更高效地解决从数据探索到模型应用的完整业务问题。
distfit 最强大的吸引力在于其极致的简洁性与强大的端到端功能的结合。无论您是需要快速探索数据分布的分析师,还是需要为复杂模拟生成数据的工程师,
distfit 都能让您用短短几行代码完成任务,极大地提升了数据科学工作流的效率和严谨性。
8. 相关推文
Note:产生如下推文列表的 Stata 命令为:
lianxh 分布 概率, md2 nocat
安装最新版 lianxh 命令:
ssc install lianxh, replace
- 侯新烁, 连玉君, 2020, 快速呈现常用分布临界值表.
- 刘潍嘉, 2024, 偏态分布数据的回归模型选择.
- 刘潍嘉, 2025, 扎马步-常用概率分布函数详解:Python篇.
- 刘潍嘉, 2025, 扎马步-常用概率分布函数详解:R语言篇.
- 刘潍嘉, 2025, 扎马步-常用概率分布函数详解:Stata篇.
- 吕卓阳, 2021, Stata 论文复现:Temperature Shocks and Economic Growth.
- 吴奕玮, 2023, 论文复现:引入注意力的考虑集模型-alogit.
- 吴小齐, 2023, 统计和计量基础:解读条件概率.
- 崔颖, 2020, Stata:用负二项分布预测蚊子存活率.
- 段义学, 2023, 因果推断中的 RA, IPW, IPWRA.
- 汪京, 2024, multihistogram-多变量直方图.
- 王恩泽, 2020, reldist-相对分布:分布差异分析和检验.
- 肖志文, 2024, 如何理解 Logit,Probit 和非线性概率模型?.
-
肖淇泳, 2021, 面板数据模型-xtdcce2:动态共同相关和截面相关.
- 连享会, 2020, Stata:何时使用线性概率模型而非Logit?.
- 连玉君, 2022, Stata绘图:唯美的函数图-自定义水平附加线和竖直附加线.
- 陈勇吏, 2020, Stata程序:Monte-Carlo-模拟之产生符合特定分布的随机数.
- 陈卓然, 2022, Stata:多元正态t截断分布的命令.
- 陈卓然, 2022, Stata:局部回归分布估计量-lpdensity.
- 陈卓然, 2022, Stata:自回归分布滞后模型简介 (ARDL).
- 陈治中, 2020, 品头论足-distcomp:组间分布差异检验.
- 陈点点, 2023, R:如何使用逆概率加权和贝叶斯倾向得分.
连享会微信小店上线啦!
Note:扫一扫进入“连享会微信小店”,你想学的课程在这里······

New! Stata 搜索神器:lianxh 和 songblGIF 动图介绍
搜: 推文、数据分享、期刊论文、重现代码 ……
👉 安装:
. ssc install lianxh
. ssc install songbl
👉 使用:
. lianxh DID 倍分法
. songbl all

🍏 关于我们
-
直通车: 👉【百度一下:连享会】即可直达连享会主页。亦可进一步添加 「知乎」,「b 站」,「面板数据」,「公开课」 等关键词细化搜索。
