如何在python中不使用逆分布函数手动生成Q-Q图

如何在python中不使用逆分布函数手动生成Q-Q图,python,math,statistics,Python,Math,Statistics,我有4种不同的分布,我已经将它们拟合到一个观察样本中。现在我想比较一下我的结果,找出最好的解决方案。我知道有很多不同的方法可以做到这一点,但我想使用分位数-分位数(q-q)图 my 4分布的公式如下: 式中,K0为第二类零阶修正贝塞尔函数,Γ为伽马函数 我的示例样式大致如下:(0.2、0.2、0.2、0.3、0.3、0.4、0.4、0.4、0.4、0.6、0.7…),因此我有多个相同的值,它们之间也有间隙 我已经阅读了这方面的说明,并尝试用python实现它们。所以,就像在链接中一样:

我有4种不同的分布,我已经将它们拟合到一个观察样本中。现在我想比较一下我的结果,找出最好的解决方案。我知道有很多不同的方法可以做到这一点,但我想使用分位数-分位数(q-q)图

my 4分布的公式如下:

式中,K0为第二类零阶修正贝塞尔函数,Γ为伽马函数

我的示例样式大致如下:(0.2、0.2、0.2、0.3、0.3、0.4、0.4、0.4、0.4、0.6、0.7…),因此我有多个相同的值,它们之间也有间隙

我已经阅读了这方面的说明,并尝试用python实现它们。所以,就像在链接中一样:

1) 我将数据从最小值排序到最大值

2) 我在区间(0,1)上计算了“n”个均匀分布的点,其中“n”是我的样本量

3) 这是我无法解决的问题

据我所知,我现在应该使用我事先计算的值(那些均匀分布的值),将它们放入上述分布的反函数中,从而计算我分布的理论分位数

以下是反函数(尽可能使用部分反函数进行计算),以供参考:

其中W是Lambert W函数,其后括号中的所有内容都是参数

问题是,显然,对于第一个分布不存在反函数。下一个可能会产生复杂的值(根下为负数,因为根据拟合b=0.55),最后两个值有一个Lambert W函数(我不知道如何在python中实现它们)

所以我的问题是,有没有办法不用逆分布函数的解析表达式来计算q-q图?


如果您能给我任何帮助,我将不胜感激

一种更简单、更传统的方法是计算每个模型的对数似然,然后选择一个具有最大对数似然的模型。你不需要cdf或分位数函数,只需要密度函数,你已经有了

对数似然是对数p(x |模型)的和,其中p(x |模型)是给定模型下基准x的概率密度。此处“模型”=通过最大化参数可能值的对数似然来选择参数的模型

通过在参数空间上积分对数似然,同时考虑分配给每个模型的任何先验概率,可以对此更加小心;这将是一种贝叶斯方法


听起来你基本上是想通过最小化Kolmogorov-Smirnov(KS)统计量来选择一个模型,尽管这个统计量的名字很重,但它非常简单——它是潜在分位数函数和经验分位数之间的差异。这是有道理的,但我认为比较日志可能性更为传统,也更为简单,因为您只需要pdf。

该死。。。抱歉,我一直专注于一个巧妙的解决方案,以某种方式绕过缺少的逆CDF,直接计算分位数(并避免任何数值方法)。但这也可以通过简单的暴力来实现

首先,您必须自己定义分布的分位数(例如,比原始分位数/经验分位数精确十倍)。然后需要计算相应的CDF值。然后,您必须将这些值逐一与问题中步骤2中计算的值进行比较。偏差最小的CDF值的相应分位数就是您要查找的分位数

此解决方案的精度受到您自己定义的分位数分辨率的限制


但也许我错了,有一个更优雅的方法来解决这个问题,那么我会很高兴听到它

碰巧有一个更简单的方法。我花了一两天的时间才在scipy.stats中找到正确的方法。我找错名字了

首先,构建
rv_continuous
的子类来表示您的一个发行版。我们知道您的发行版的pdf,所以这就是我们定义的。在这种情况下,只有一个参数。如果需要更多,只需将它们添加到
def
语句中,并根据需要在
return
语句中使用它们

>>> from scipy import stats
>>> param = 3/2
>>> from math import exp
>>> class NoName(stats.rv_continuous):
...     def _pdf(self, x, param):
...         return param*exp(-param*x)
...     
现在创建这个对象的一个实例,声明其支持度的下限(即r.v.可以假定的最低值),以及调用的参数

>>> noname = NoName(a=0, shapes='param')
我没有一个真正的价值观样本可供使用。我将创建一个伪随机样本

>>> sample = noname.rvs(size=100, param=param)
对其进行排序,使其成为所谓的“经验cdf”

>>> empirical_cdf = sorted(sample)
该样本有100个元素,因此生成100个点,在该点处对反向cdf或分位数函数进行采样,如您参考的论文中所述

>>> theoretical_points = [(_-0.5)/len(sample) for _ in range(1, 1+len(sample))]
获取这些点的分位数函数值

>>> theoretical_cdf = [noname.ppf(_, param=param) for _ in theoretical_points]
把它全部画出来

>>> from matplotlib import pyplot as plt
>>> plt.plot([0,3.5], [0, 3.5], 'b-')
[<matplotlib.lines.Line2D object at 0x000000000921B400>]
>>> plt.scatter(empirical_cdf, theoretical_cdf)
<matplotlib.collections.PathCollection object at 0x000000000921BD30>
>>> plt.show()
>>从matplotlib导入pyplot作为plt
>>>plt.绘图([0,3.5],[0,3.5],“b-”)
[]
>>>plt.散射(经验cdf、理论cdf)
>>>plt.show()
这是结果的Q-Q图


您的意思是您已经估计了一个或多个样本的每个密度函数的参数吗?@BillBell我已经根据一个样本计算了我函数的所有参数。Q-Q图用于比较两个样本(请参阅)。我怀疑您想要比较四个估计的CDF。@BillBell我想要比较我的4个计算函数/CDF和我的示例/ecdf。结果应如以下论文第7页图3的Q-Q图所示:谢谢您的回答!我知道对数似然估计,但我想创建q-q图(以及p-p图,但这更容易)