Problem pojawia się, jeśli pierwsze wywołanie funkcji przeżycia znajduje się w zakresie, który powinien wynosić zero (zobacz mój komentarz do poprzedniej odpowiedzi). Np. W przypadku wywołań hypergeom.sf (x, M, n, N) nie powiedzie się, jeśli pierwszym wywołaniem funkcji hipergeometrycznej do funkcji jest sytuacja, w której x> n, gdzie funkcja przeżycia zawsze będzie wynosić zero.
Można trywialnie to naprawić tymczasowo przez:
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
Teraz, jeśli nie masz edycji na /usr/share/pyshared/scipy/stats/distributions.py problemu (lub odpowiednik pliku), poprawka prawdopodobnie na linii 3966, gdzie teraz to brzmi:
place(output,cond,self._sf(*goodargs))
if output.ndim == 0:
return output[()]
return output
Ale jeśli go zmienić na:
if output.ndim == 0:
return output[()]
place(output,cond,self._sf(*goodargs))
if output.ndim == 0:
return output[()]
return output
Teraz działa bez indeksu IndexError. Zasadniczo, jeśli wynik jest zerowy, ponieważ nie sprawdza, próbuje wywołać miejsce, kończy się niepowodzeniem i nie generuje dystrybucji. (Nie dzieje się tak, jeśli poprzednia dystrybucja została już utworzona, co prawdopodobnie powoduje, że nie została ona przechwycona przez wcześniejsze testy.) Zauważ, że miejsce (zdefiniowane w numpy's function_base.py) zmieni elementy tablicy (chociaż ja nie jestem pewien, czy to zmienia wymiarowość), więc może być najlepiej, aby nadal pozostawić zerową kontrolę po miejscu też. Nie przetestowałem tego w pełni, aby sprawdzić, czy ta zmiana nie powoduje niczego innego (i dotyczy wszystkich dyskretnych rozkładów zmiennych losowych), więc może najlepiej wykonać pierwszą poprawkę.
To łamie; np. stats.hypergeom.sf (1,10,2,5) zwraca wartość zero (zamiast 2/9).
Ta poprawka wydaje się działać znacznie lepiej, w tej samej sekcji:
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
on robi to samo na Python 2.6.6 na Debianie. – eumiro
Cokolwiek jest warte, brzmi to jak błąd, a zatem może być lepiej zapytany na liście użytkowników scipy: http://mail.scipy.org/mailman/listinfo/scipy-user Jest bardziej prawdopodobne, że dostanie uwaga twórców tam ... –
Otworzyłem bilet na to: http://projects.scipy.org/scipy/ticket/1291. Jak wspomniał Joe Kington, przydatne byłoby zgłaszanie błędów lub nieoczekiwanych zachowań do listy mailingowej lub do śledzenia błędów pakietu. – user333700