Gráfico de cuantiles-cuantiles utilizando SciPy


85

¿Cómo crearías un gráfico qq usando Python?

Suponiendo que tiene un gran conjunto de medidas y está utilizando alguna función de trazado que toma valores XY como entrada. La función debe graficar los cuantiles de las medidas contra los cuantiles correspondientes de alguna distribución (normal, uniforme ...).

La gráfica resultante nos permite luego evaluar en nuestra medición si sigue la distribución supuesta o no.

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

Tanto R como Matlab proporcionan funciones listas para usar para esto, pero me pregunto cuál sería el método más limpio para implementar en Python.



1
qqplot y probplots con muchas opciones: statsmodels.sourceforge.net/devel/…
Josef

Respuestas:


105

Creo que scipy.stats.probplothará lo que quieras. Consulte la documentación para obtener más detalles.

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()

Resultado

ingrese la descripción de la imagen aquí


A veces he visto algunas líneas de confianza punteadas que se estrechan en el medio y son como una trompeta en los extremos. ¿Puede agregar estas "líneas guía" a la trama?
Norfeldt

21
Bien, pero esta es una gráfica de probabilidad (una muestra frente a una distribución teórica). Una gráfica qq compara dos muestras. itl.nist.gov/div898/handbook/eda/section3/qqplot.htm itl.nist.gov/div898/handbook/eda/section3/probplot.htm
Ricky Robinson

7
@RickyRobinson Parece que muchas fuentes (incluida la wikipedia) contradicen el manual de NIST. Prácticamente cualquier otra fuente afirma que una gráfica QQ tiene cuantiles teóricos en el eje horizontal y cuantiles de datos verticalmente. En cualquier caso, la distinción es académica: trazar una muestra es esencialmente lo mismo que usar la función de distribución empírica. De cualquier manera, está trazando los cuantiles de una distribución frente a otra.
Peter

1
Estoy de acuerdo con @RickyRobinson, esta no es la respuesta correcta a esta pregunta. Las gráficas QQ y las gráficas prob son diferentes a pesar de que ambos son cuantiles de una distribución frente a otra.
Florent

48

El uso qqplotde statsmodels.apies otra opción:

Ejemplo muy básico:

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()

Resultado:

ingrese la descripción de la imagen aquí

La documentación y más ejemplos están aquí.


1
@ tommy.carstensen se separó deliberadamente de scipyastatsmodels
SARose

3
Solo una nota. Su ejemplo traza la línea para la distribución normal estándar. Para obtener una línea estandarizada (escalada por la desviación estándar de la muestra dada y tener la media agregada) como en el ejemplo de @Geoff, debe establecer line = 's' en lugar de line = '45 '
Mike

+1 para esta respuesta. Creo que es importante concentrar más recursos en un solo paquete de estadísticas. statsmodelssería una buena elección.
Ken T

20

Si necesita hacer un gráfico QQ de una muestra frente a otra, statsmodels incluye qqplot_2samples (). Al igual que Ricky Robinson en un comentario anterior, esto es lo que considero una gráfica QQ frente a una gráfica de probabilidad que es una muestra frente a una distribución teórica.

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


11
Esta implementación de qqplot no parece manejar muestras con diferentes tamaños, lo cual es divertido porque una de las grandes ventajas de una gráfica QQ es que se pueden comparar muestras con diferentes tamaños ...
Robert Muil

5

Se me ocurrió esto. Quizás puedas mejorarlo. Especialmente el método de generar los cuantiles de la distribución me parece engorroso.

Puede reemplazar np.random.normalcon cualquier otra distribución de np.randompara comparar los datos con otras distribuciones.

#!/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

Para aumentar la confusión en torno a las gráficas QQ y las gráficas de probabilidad en los mundos Python y R, esto es lo que dice el manual SciPy :

" probplotgenera una gráfica de probabilidad, que no debe confundirse con una gráfica QQ o PP. Statsmodels tiene una funcionalidad más extensa de este tipo, consulte statsmodels.api.ProbPlot".

Si lo prueba scipy.stats.probplot, verá que de hecho compara un conjunto de datos con una distribución teórica. Gráficos QQ, OTOH, comparan dos conjuntos de datos (muestras).

R tiene funciones qqnorm, qqploty qqline. De la ayuda de R (versión 3.6.3):

qqnormes una función genérica cuyo método predeterminado produce una gráfica QQ normal de los valores en y. qqlineagrega una línea a un gráfico cuantil-cuantílico "teórico", por defecto normal, que pasa por los cuantiles probs, por defecto el primer y tercer cuartiles.

qqplot produce una gráfica QQ de dos conjuntos de datos.

En resumen, R's qqnormofrece la misma funcionalidad que scipy.stats.probplotproporciona la configuración predeterminada dist=norm. Pero el hecho de que lo hayan llamado qqnormy que se supone que "produce una gráfica QQ normal" puede confundir fácilmente a los usuarios.

Finalmente, una advertencia. Estos gráficos no reemplazan las pruebas estadísticas adecuadas y deben usarse solo con fines ilustrativos.


2

¿Qué tan grande es su muestra? Aquí hay otra opción para probar sus datos contra cualquier distribución usando la biblioteca OpenTURNS . En el siguiente ejemplo, genero una muestra x de 1.000.000 de números a partir de una distribución uniforme y la pruebo con una distribución normal. Puede reemplazar x por sus datos si lo modifica comox= [[x1], [x2], .., [xn]]

import openturns as ot

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

En mi cuaderno de Jupyter, veo: ingrese la descripción de la imagen aquí

Si está escribiendo un guión, puede hacerlo de manera más adecuada

from openturns.viewer import View`
import matplotlib.pyplot as plt
View(g)
plt.show()

1

Puedes usar 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()

Aquí probplot dibuja las medidas del gráfico frente a la distribución normal que se especificó en dist = "norm"

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.