Wykres kwantyl-kwantyl przy użyciu SciPy

85

Jak utworzyłbyś wykres qq za pomocą Pythona?

Zakładając, że masz duży zestaw pomiarów i używasz jakiejś funkcji kreślącej, która przyjmuje wartości XY jako dane wejściowe. Funkcja powinna wykreślić kwantyle pomiarów względem odpowiednich kwantyli pewnego rozkładu (normalnego, jednorodnego ...).

Wynikowy wykres pozwala nam następnie ocenić w naszym pomiarze, czy jest zgodny z założonym rozkładem, czy nie.

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

Zarówno R, jak i Matlab zapewniają gotowe funkcje do tego, ale zastanawiam się, jaka byłaby najczystsza metoda implementacji w Pythonie.

Jan
źródło
2
Patrzyłeś na probplot? docs.scipy.org/doc/scipy/reference/generated/…
Geoff,
1
qqplot i probplot z wieloma opcjami: statsmodels.sourceforge.net/devel/…
Josef

Odpowiedzi:

105

Myślę, że scipy.stats.probplotzrobi to, co chcesz. Więcej szczegółów można znaleźć w dokumentacji .

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

Wynik

wprowadź opis obrazu tutaj

Geoff
źródło
Czasami widziałem przerywane linie pewności, które zwężają się pośrodku i na końcach przypominają trąbkę. Czy możesz dodać te „linie pomocnicze” do fabuły?
Norfeldt
21
Ok, ale to jest wykres prawdopodobieństwa (próbka vs rozkład teoretyczny). Wykres qq porównuje dwie próbki. itl.nist.gov/div898/handbook/eda/section3/qqplot.htm itl.nist.gov/div898/handbook/eda/section3/probplot.htm
Ricky Robinson
7
@RickyRobinson Wygląda na to, że wiele źródeł (w tym wikipedia) jest sprzecznych z podręcznikiem NIST. Prawie każde inne źródło podaje, że wykres QQ ma teoretyczne kwantyle na osi poziomej i kwantyle danych w pionie. W każdym razie rozróżnienie to ma charakter akademicki: wykreślenie próbki jest zasadniczo tym samym, co użycie funkcji dystrybucji empirycznej. Tak czy inaczej, wykreślasz kwantyle jednego z podziałów względem drugiego.
Peter
1
Zgadzam się z @RickyRobinson, to nie jest poprawna odpowiedź na to pytanie. Wykresy QQ i wykresy prob są różne, mimo że oba kwantyle dystrybucji są przeciwstawne.
Florent
48

Korzystanie qqplotz statsmodels.apito kolejna opcja:

Bardzo podstawowy przykład:

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

Wynik:

wprowadź opis obrazu tutaj

Dokumentacja i więcej przykładów są tutaj

Akavall
źródło
1
@ tommy.carstensen został celowo oddzielony od scipydostatsmodels
SARose
3
Tylko uwaga. Twój przykład rysuje linię dla standardowego rozkładu normalnego. Aby uzyskać znormalizowaną linię (skalowaną przez odchylenie standardowe danej próbki i dodaną średnią), jak w przykładzie @Geoff, musisz ustawić line = 's' zamiast line = '45 '
Mike
+1 za tę odpowiedź. Myślę, że ważne jest, aby skupić więcej zasobów na jednym pakiecie statystycznym. statsmodelsbyłby dobrym wyborem.
Ken T
20

Jeśli potrzebujesz wykonać wykres QQ jednej próbki względem drugiej, statsmodels zawiera qqplot_2samples (). Podobnie jak Ricky Robinson w powyższym komentarzu, myślę o tym jako o wykresie QQ kontra wykresie prawdopodobieństwa, który jest próbką względem rozkładu teoretycznego.

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

ccap
źródło
11
Ta implementacja qqplot wydaje się nie obsługiwać próbek o różnych rozmiarach, co jest zabawne, ponieważ jedną z największych zalet wykresu QQ jest to, że można porównać próbki o różnych rozmiarach ...
Robert Muil
5

Wymyśliłem to. Może możesz to poprawić. Szczególnie metoda generowania kwantyli rozkładu wydaje mi się uciążliwa.

Możesz zastąpić np.random.normalinną dystrybucję z, np.randomaby porównać dane z innymi dystrybucjami.

#!/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)
Jan
źródło
2

Aby dodać do zamieszania wokół wykresów QQ i wykresów prawdopodobieństwa w światach Python i R, oto co mówi podręcznik SciPy :

" probplotgeneruje wykres prawdopodobieństwa, którego nie należy mylić z wykresem QQ lub PP. Statsmodels ma bardziej rozbudowaną funkcjonalność tego typu, patrz statsmodels.api.ProbPlot."

Jeśli spróbujesz scipy.stats.probplot, zobaczysz, że rzeczywiście porównuje zbiór danych z rozkładem teoretycznym. Wykresy QQ, OTOH, porównaj dwa zestawy danych (próbki).

R ma funkcje qqnorm, qqploti qqline. Z pomocy R (wersja 3.6.3):

qqnormjest funkcją ogólną, której domyślna metoda tworzy normalny wykres QQ wartości w y. qqlinedodaje linię do „teoretycznego”, domyślnie normalnego wykresu kwantyl-kwantyl, który przechodzi przez kwantyle probs, domyślnie pierwszy i trzeci kwartyl.

qqplot tworzy wykres QQ dwóch zestawów danych.

Krótko mówiąc, R qqnormoferuje tę samą funkcjonalność, która scipy.stats.probplotzapewnia ustawienie domyślne dist=norm. Ale fakt, że go nazwali qqnormi że ma on „tworzyć normalny wykres QQ” może łatwo zmylić użytkowników.

Na koniec słowo ostrzeżenia. Te wykresy nie zastępują właściwych testów statystycznych i powinny być używane wyłącznie w celach ilustracyjnych.

Laryx Decidua
źródło
2

Jak duża jest twoja próbka? Oto kolejna opcja przetestowania danych w dowolnej dystrybucji przy użyciu biblioteki OpenTURNS . W poniższym przykładzie generuję próbkę x zawierającą 1.000.000 liczb z rozkładu jednorodnego i testuję ją z rozkładem normalnym. Możesz zastąpić x swoimi danymi, jeśli zmienisz go nax= [[x1], [x2], .., [xn]]

import openturns as ot

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

W moim notatniku Jupyter widzę: wprowadź opis obrazu tutaj

Jeśli piszesz scenariusz, możesz zrobić to lepiej

from openturns.viewer import View`
import matplotlib.pyplot as plt
View(g)
plt.show()
Jean A.
źródło
1

Możesz użyć 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)
sushmit
źródło
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()

Tutaj probplot narysuj wykres pomiarów względem rozkładu normalnego, który jest wyrażony jako dist = "norma"

Ravi G
źródło