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