2014-06-23 19 views
15

Supponiamo che ho un po 'di dati che ho ottenuto empiricamente:Come eseguire un test di qualità del chi quadrato utilizzando le librerie scientifiche in Python?

from scipy import stats 
size = 10000 
x = 10 * stats.expon.rvs(size=size) + 0.2 * np.random.uniform(size=size) 

Si esponenzialmente distribuita (con un po' di rumore) e voglio verificare questo utilizzando una bontà chi-quadrato di adattamento di prova (GoF). Qual è il modo più semplice per farlo usando le librerie scientifiche standard in Python (ad esempio scipy o statsmodels) con il minor numero di passi e assunzioni manuali?

posso montare un modello con:

param = stats.expon.fit(x) 
plt.hist(x, normed=True, color='white', hatch='/') 
plt.plot(grid, distr.pdf(np.linspace(0, 100, 10000), *param)) 

distribution and empirical data plot

E 'molto elegante per calcolare il Kolmogorov-Smirnov test.

>>> stats.kstest(x, lambda x : stats.expon.cdf(x, *param)) 
(0.0061000000000000004, 0.85077099515985011) 

Tuttavia, non riesco a trovare un buon metodo per calcolare il test del chi quadrato.

C'è un chi-squared GoF function in statsmodel, ma si presuppone una distribuzione discreta (e la distribuzione esponenziale è continua).

Il official scipy.stats tutorial copre solo un caso per una distribuzione personalizzata e le probabilità sono create giocando con molte espressioni (npoint, npoints, nbound, normbound), quindi non mi è chiaro come farlo per altre distribuzioni. chisquare examples presuppone che i valori previsti e DoF siano già stati ottenuti.

Inoltre, non sto cercando un modo per eseguire "manualmente" il test come era already discussed here, ma vorrei sapere come applicare una delle funzioni di libreria disponibili.

+2

Per quanto ne so, non esiste una funzione "ufficiale" libreria Python per il test CHISQUARE che include categorizzazione per distribuzione continua. Consiglierei di usare Anderson-Darling, scipy's anderson, che dovrebbe avere un potere migliore, se non ricordo male. – user333700

+0

OK, ma da quello che posso vedere l'implementazione ['anderson' in SciPy] (http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.anderson.html#scipy.stats.anderson) supporta solo 5 distribuzioni. – metakermit

+0

Sì, ma anderson supporta la distribuzione esponenziale che si sta utilizzando. Se si stimano i parametri della distribuzione e si desidera che funzioni per qualsiasi distribuzione, si torna al binning per la chisquare o all'avvio di un altro dei test gof. – user333700

risposta

3

una soluzione approssimata per la parità di bidoni di probabilità:

  • stimare i parametri della distribuzione
  • Utilizzare il CDF inversa, PPF se è uno scipy.stats.distribution, per ottenere il binedges per una probabilità normale griglia, es distribution.ppf(np.linspace(0, 1, n_bins + 1), *args)
  • Poi, l'uso np.histogram per contare il numero di osservazioni in ogni bin

quindi utilizzare il test CHISQUARE sulle frequenze.

Un'alternativa sarebbe quella di trovare i bordi del raccoglitore dai percentili dei dati ordinati e utilizzare il cdf per trovare le probabilità effettive.

Questo è solo approssimativo, poiché la teoria per il test di chisquare presuppone che i parametri siano stimati con la massima verosimiglianza sui dati associati. E non sono sicuro se la selezione dei binari sulla base dei dati influenzi la distribuzione asintotica.

Non ho esaminato questo a lungo. Se una soluzione approssimativa non è abbastanza buona, allora raccomanderei di porre la domanda su stats.stackexchange.

+1

Ri: se il binning influenzerà la distribuzione asintotogica, è necessario farlo. Potrebbe essere trascurabile, però. Per il binning e l'utilizzo del test chi-quadrato, questa sarà la risposta giusta. +1 – gung

+0

@Gung Dipende dalla natura degli aysymptotics. Credo che se si adattano i punti di divisione in un modo che consenta al conteggio minimo del contenitore previsto di crescere, la distribuzione asintotica dovrebbe essere il chi quadrato. Ma la distribuzione asintotica è irrilevante: ciò che conta è la distribuzione * effettiva *, ed è chiaro che la definizione dei punti di riferimento basati sui dati introdurrà cambiamenti arbitrari in quella distribuzione (se solo un po '). – whuber

+0

@ user333700 Potresti fornire un esempio della soluzione che hai fornito. Ho provato questo: 'In: np.random.seed (453)', 'In: data_1 = stats.norm.rvs (size = 10000)', 'In: loc, scale = stats.norm.fit (data_1) ',' In: data_2 = stats.norm (loc, scale) .rvs (size = 10000) ',' In: data_1_hist = np.histogram (data_1, bins = 10) ',' In: data_2_hist = np.histogram (data_2, bin = 10) ',' In: print stats.chisquare (data_2_hist [0], data_1_hist [0]) ',' Out: (statistica = 564.43784612331842, pvalue = 8.926608295951506e-116) '. Inoltre, come dovrebbe essere usato 'distribution.ppf (np.linspace (0, 1, n_bins + 1), * args)'? – Julia

2

Perché è necessario "verificare" che sia esponenziale? Sei sicuro di aver bisogno di un test statistico? Posso praticamente garantire che non è in definitiva esponenziale & il test sarebbe significativo se si dispone di dati sufficienti, rendendo la logica di utilizzare il test piuttosto forzato.Potrebbe essere utile leggere questa discussione CV: Is normality testing 'essentially useless'? o la mia risposta qui: Testing for heteroscedasticity with many observations.

In genere è preferibile utilizzare una trama qq e/o una trama pp (a seconda se si è preoccupati per l'adattamento nella coda o al centro della distribuzione, vedere la risposta qui: PP-plots vs. QQ-plots). Le informazioni su come fare QQ-trame in Python SciPy può essere trovato in questo SO discussione: Quantile-Quantile plot using SciPy

+0

Non sapevo di QQ-plotting. Lo esaminerò, grazie. La mia motivazione è semplicemente quella di essere in grado di dare qualche misura quantitativa di quanto possa essere certa la distribuzione del set di dati (qualcosa di più formale di "guardare l'istogramma, sembra esponenziale"). Ho pensato che i test di bontà fisica mi possono aiutare qui, ma ora vedo dalla discussione che hai collegato che potrebbe non essere così semplice :) – metakermit

+1

Ci sono modi per quantificare quanto siano vicine due distribuzioni. Un test statistico * non ti dà proprio questo, b/c il valore p è una funzione sia di quella distanza che del tuo N. Puoi usare la correlazione dei punti in una trama qq- o pp (ma sopportare tenendo presente che r sarà sempre vicino a 1), potresti anche usare qualcosa come [KL] (http://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence) (non in realtà una distanza). Puoi anche fare una domanda sul CV sul modo migliore per ottenere una misura quantitativa della distanza b/t 2 dist. Risulterà complicato e dipende da ciò di cui hai bisogno. – gung

+1

chisquare ti dà una misura della distanza, puoi anche scegliere qualcun altro test del gof come "misura della distanza". Tuttavia, non ti dirà molto di grandezza. I problemi non sono specifici per i test Gof. In tutti i test di ipotesi, ci si deve preoccupare di avere poca energia in campioni di dimensioni ridotte e troppa potenza in campioni di grandi dimensioni. statsmodels ha funzioni per calcolare la dimensione dell'effetto e la potenza di un test di chisquare, ad es. http://statsmodels.sourceforge.net/devel/generated/statsmodels.stats.gof.chisquare_effectsize.html – user333700

Problemi correlati