有人可以解释scipy中超几何分布的奇怪行为吗?

时间:2010-09-28 12:55:34

标签: python scipy

我在Mac OS X 10.6.4上运行Python 2.6.5(这不是本机版本,我自己安装),使用Scipy 0.8.0。如果我执行以下操作:

>>> from scipy.stats import hypergeom
>>> hypergeom.sf(5,10,2,5)

我得到IndexError。然后我做:

>>> hypergeom.sf(2,10,2,2)
-4.44....

我怀疑负值是由于浮点精度不好造成的。然后我又做了第一个:

>>> hypergeom.sf(5,10,2,5)
0.0

现在它有效!有人可以解释一下吗?你也看到了这种行为吗?

2 个答案:

答案 0 :(得分:3)

如果对生存函数的第一次调用显然在零范围内(参见我对上一个答案的评论),问题似乎就出现了。例如,对于对hypergeom.sf(x,M,n,N)的调用,如果对函数的超几何函数的第一次调用是x> 1的情况,则它失败。 n,生存函数总是为零。

您可以通过以下方式暂时解决此问题:

def new_hypergeom_sf(k, *args, **kwds):
    from scipy.stats import hypergeom
    (M, n, N) = args[0:3]
    try:
        return hypergeom.sf(k, *args, **kwds)
    except Exception as inst:
        if k >= n and type(inst) == IndexError:
            return 0 ## or conversely 1 - hypergeom.cdf(k, *args, **kwds)
        else:
            raise inst

现在,如果编辑/usr/share/pyshared/scipy/stats/distributions.py(或等效文件)没有问题,修复程序很可能在第3966行,其中现在的内容为:

<击>
    place(output,cond,self._sf(*goodargs))
    if output.ndim == 0:
        return output[()]
    return output

但是如果你把它改成:

    if output.ndim == 0:
        return output[()]
    place(output,cond,self._sf(*goodargs))
    if output.ndim == 0:
        return output[()]
    return output

它现在没有IndexError。基本上,如果输出是零维,因为它未通过检查,它会尝试调用place,failed,并且不会生成分布。 (如果先前的分布已经创建,这可能不会发生,这可能是为什么没有在早期的测试中捕获的。)注意,地方(在numpy的function_base.py中定义)将改变数组的元素(虽然我是不确定它是否会改变维度)所以最好还是让它在放置之后离开0暗淡检查。我还没有对此进行全面测试,以确定此更改是否会破坏其他任何内容(并且它适用于所有离散随机变量分布),因此最好先进行修改。

确实打破了它;例如,stats.hypergeom.sf(1,10,2,5)返回零(而不是2/9)。

这个修补程序似乎在同一部分中运行得更好:

class rv_discrete(rv_generic):
...
    def sf(self, k, *args, **kwds):
    ...
        if any(cond):
            place(output,cond,self._sf(*goodargs))
        if output.ndim == 0:
            return output[()]
        return output

答案 1 :(得分:0)

我不知道python,但函数定义如下: hypergeom.sf(x,M,n,N,loc = 0)

M是感兴趣的对象的数量,N是对象的总数,n是您“选择一个”的频率(对不起,德国统计学家)。

如果你有一个有20个球的碗,其中7个为黄色(有趣的黄色),则N为20,M为7。

当M> N?

时,对于(无意义)情况,该函数的行为可能未定义