Quantile-Quantile Plot utilizzando SciPy


87

Come creeresti un grafico qq usando Python?

Supponendo che si disponga di un ampio insieme di misurazioni e si utilizzi una funzione di tracciamento che accetta valori XY come input. La funzione dovrebbe tracciare i quantili delle misurazioni rispetto ai corrispondenti quantili di una certa distribuzione (normale, uniforme ...).

Il grafico risultante ci consente quindi di valutare nella nostra misurazione che segue o meno la distribuzione presunta.

http://en.wikipedia.org/wiki/Quantile-quantile_plot

Sia R che Matlab forniscono funzioni già pronte per questo, ma mi chiedo quale sarebbe il metodo più pulito per l'implementazione in Python.



1
qqplot e probplots con molte opzioni: statsmodels.sourceforge.net/devel/…
Josef

Risposte:


105

Penso che scipy.stats.probplotfarà quello che vuoi. Vedere la documentazione per maggiori dettagli.

import numpy as np 
import pylab 
import scipy.stats as stats

measurements = np.random.normal(loc = 20, scale = 5, size=100)   
stats.probplot(measurements, dist="norm", plot=pylab)
pylab.show()

Risultato

inserisci qui la descrizione dell'immagine


A volte ho visto alcune linee di confidenza tratteggiate che si restringono al centro e sono come una tromba alle estremità. Puoi aggiungere queste "linee guida" alla trama?
Norfeldt

21
Ok, ma questo è un grafico delle probabilità (un campione contro una distribuzione teorica). Un grafico qq confronta due campioni. itl.nist.gov/div898/handbook/eda/section3/qqplot.htm itl.nist.gov/div898/handbook/eda/section3/probplot.htm
Ricky Robinson

7
@RickyRobinson Sembra che molte fonti (inclusa wikipedia) contraddicono il manuale del NIST. Praticamente qualsiasi altra fonte afferma che un grafico QQ ha quantili teorici sull'asse orizzontale e quantili di dati verticalmente. In ogni caso, la distinzione è accademica: tracciare un campione è essenzialmente lo stesso che usare la funzione di distribuzione empirica. In ogni caso, stai tracciando i quantili di una distribuzione rispetto a un altro.
Peter il

1
Sono d'accordo con @RickyRobinson, questa non è la risposta corretta a questa domanda. I grafici QQ e i grafici prob sono diversi anche se entrambi i quantili di una distribuzione rispetto a un altro.
Florent

49

L'utilizzo qqplotdi statsmodels.apiè un'altra opzione:

Esempio molto semplice:

import numpy as np
import statsmodels.api as sm
import pylab

test = np.random.normal(0,1, 1000)

sm.qqplot(test, line='45')
pylab.show()

Risultato:

inserisci qui la descrizione dell'immagine

La documentazione e altri esempi sono qui


1
@ tommy.carstensen è stato deliberatamente separato da scipyastatsmodels
SARose

5
Solo una nota. Il tuo esempio traccia la linea per la distribuzione normale standard. Per ottenere una linea standardizzata (scalata dalla deviazione standard del campione dato e aggiungere la media) come nell'esempio @Geoff, è necessario impostare line = 's' invece di line = '45 '
Mike

+1 per questa risposta. Penso che sia importante concentrare più risorse su un unico pacchetto per le statistiche. statsmodelssarebbe una buona scelta.
Ken T

20

Se è necessario eseguire un grafico QQ di un campione rispetto a un altro, statsmodels include qqplot_2samples (). Come Ricky Robinson in un commento sopra, questo è quello che penso come un grafico QQ vs un grafico probabilistico che è un campione contro una distribuzione teorica.

http://statsmodels.sourceforge.net/devel/generated/statsmodels.graphics.gofplots.qqplot_2samples.html


11
Questa implementazione di qqplot non sembra gestire campioni con dimensioni diverse, il che è divertente perché uno dei grandi vantaggi di un grafico QQ è che si possono confrontare campioni con dimensioni diverse ...
Robert Muil

5

Ho pensato a questo. Forse puoi migliorarlo. Soprattutto il metodo per generare i quantili della distribuzione mi sembra macchinoso.

È possibile sostituire np.random.normalcon qualsiasi altra distribuzione di np.randomper confrontare i dati con altre distribuzioni.

#!/bin/python

import numpy as np

measurements = np.random.normal(loc = 20, scale = 5, size=100000)

def qq_plot(data, sample_size):
    qq = np.ones([sample_size, 2])
    np.random.shuffle(data)
    qq[:, 0] = np.sort(data[0:sample_size])
    qq[:, 1] = np.sort(np.random.normal(size = sample_size))
    return qq

print qq_plot(measurements, 1000)


2

Per aumentare la confusione intorno ai grafici QQ e ai grafici di probabilità nei mondi Python e R, questo è ciò che dice il manuale di SciPy :

" probplotgenera un grafico delle probabilità, che non deve essere confuso con un grafico QQ o PP. Statsmodels ha funzionalità più estese di questo tipo, vedere statsmodels.api.ProbPlot."

Se ci provi scipy.stats.probplot , vedrai che effettivamente confronta un set di dati con una distribuzione teorica. I grafici QQ, OTOH, confrontano due set di dati (campioni).

R ha funzioni qqnorm, qqplote qqline. Dalla guida R (Versione 3.6.3):

qqnormè una funzione generica il cui metodo predefinito produce un normale grafico QQ dei valori in y. qqlineaggiunge una linea a un grafico quantile-quantile "teorico", per impostazione predefinita normale, che passa attraverso i quantili probs, per impostazione predefinita il primo e il terzo quartile.

qqplot produce un grafico QQ di due set di dati.

In breve, R's qqnormoffre la stessa funzionalità che scipy.stats.probplotfornisce l'impostazione predefinita dist=norm. Ma il fatto che l'abbiano chiamato qqnorme che dovrebbe "produrre un normale grafico QQ" può facilmente confondere gli utenti.

Infine, una parola di avvertimento. Questi grafici non sostituiscono i test statistici appropriati e dovrebbero essere usati solo a scopo illustrativo.


1

Puoi usare il bokeh

from bokeh.plotting import figure, show
from scipy.stats import probplot
# pd_series is the series you want to plot
series1 = probplot(pd_series, dist="norm")
p1 = figure(title="Normal QQ-Plot", background_fill_color="#E8DDCB")
p1.scatter(series1[0][0],series1[0][1], fill_color="red")
show(p1)

1
import numpy as np 
import pylab 
import scipy.stats as stats
measurements = np.random.normal(loc = 20, scale = 5, size=100)   
stats.probplot(measurements, dist="norm", plot=pylab)
pylab.show()

Qui probplot disegna le misurazioni del grafico rispetto alla distribuzione normale specificata in dist = "norm"


0

Quanto è grande il tuo campione? Ecco un'altra opzione per testare i tuoi dati rispetto a qualsiasi distribuzione utilizzando la libreria OpenTURNS . Nell'esempio seguente, genero un campione x di 1.000.000 di numeri da una distribuzione Uniforme e lo testò contro una distribuzione Normale. Puoi sostituire x con i tuoi dati se lo rimodelli comex= [[x1], [x2], .., [xn]]

import openturns as ot

x = ot.Uniform().getSample(1000000)
g = ot.VisualTest.DrawQQplot(x, ot.Normal())
g

Nel mio Jupyter Notebook, vedo: inserisci qui la descrizione dell'immagine

Se stai scrivendo una sceneggiatura, puoi farlo in modo più corretto

from openturns.viewer import View`
import matplotlib.pyplot as plt
View(g)
plt.show()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.