Проблема, похоже, возникает из-за того, что первый вызов функции выживания находится в диапазоне, который, очевидно, должен быть равен нулю (см. Мой комментарий к предыдущему ответу). Например, для вызовов hypergeom.sf (x, M, n, N) он завершается неудачно, если первый вызов гипергеометрической функции для функции представляет собой ситуацию, когда x> 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, терпит неудачу и не генерирует распределение. (Этого не происходит, если предыдущий дистрибутив уже был создан, что, вероятно, не было обнаружено в предыдущих тестах.) Обратите внимание, что место (определенное в numpy's function_base.py) изменит элементы массива (хотя я не уверен, изменяет ли он размерность), поэтому лучше оставить его, также оставив проверку 0 dim после места. Я не полностью проверил это, чтобы увидеть, нарушает ли это изменение что-то еще (и оно применяется ко всем распределениям дискретных случайных величин), поэтому, возможно, лучше всего сделать первое исправление.
Это ломает его; например, 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