我在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
现在它有效!有人可以解释一下吗?你也看到了这种行为吗?
答案 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?
时,对于(无意义)情况,该函数的行为可能未定义