Квантильно-квантильний графік за допомогою SciPy


85

Як би ви створили qq-графік за допомогою Python?

Припускаючи, що у вас великий набір вимірювань і ви використовуєте якусь функцію побудови графіків, яка приймає значення XY як вхідні дані. Функція повинна будувати квантилі вимірювань щодо відповідних квантилів певного розподілу (нормального, рівномірного ...).

Отриманий графік дозволяє нам потім оцінити, коли ми вимірюємо, чи передбачається розподіл чи ні.

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

І R, і Matlab надають готові функції для цього, але мені цікаво, яким був би найчистіший метод для реалізації в Python.



1
qqplot та probplots з безліччю опцій: statsmodels.sourceforge.net/devel/…
Йозеф

Відповіді:


105

Я думаю, що scipy.stats.probplotзробиш те, що ти хочеш. Детальніше див. У документації .

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

Результат

введіть тут опис зображення


Іноді я бачив кілька пунктирних впевнених ліній, які звужуються посередині і нагадують трубу в кінцях. Чи можете ви додати ці «орієнтири» до сюжету?
Норфельдт

21
Гаразд, але це графік вірогідності (вибірка проти теоретичного розподілу). Графік qq порівнює дві вибірки. itl.nist.gov/div898/handbook/eda/section3/qqplot.htm itl.nist.gov/div898/handbook/eda/section3/probplot.htm
Рікі Робінсон,

7
@RickyRobinson Здається, багато джерел (включаючи wikipedia) суперечать довіднику NIST. Практично будь-яке інше джерело стверджує, що графік QQ має теоретичні квантили на горизонтальній осі, а кванти даних - по вертикалі. У будь-якому випадку, відмінність академічна: побудова вибірки по суті така ж, як використання емпіричної функції розподілу. У будь-якому випадку, ви складаєте змову одного квантилу дісітрації проти іншого.
Пітер

1
Я згоден з @RickyRobinson, це не правильна відповідь на це питання. Графіки QQ та діаграми зразків різні, хоча вони обидва кванти розподілу проти іншого.
Флоран

48

Використання qqplotз statsmodels.apiінший варіант:

Дуже базовий приклад:

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

Результат:

введіть тут опис зображення

Документація та інші приклади тут


1
@ tommy.carstensen це було навмисно відокремлено від scipyдоstatsmodels
SARose

3
Просто примітка. Ваш приклад малює лінію для звичайного нормального розподілу. Щоб отримати стандартизований рядок (масштабований за стандартним відхиленням даної вибірки та додаючи середнє значення), як у прикладі @Geoff, вам потрібно встановити line = 's' замість line = '45 '
Майк,

+1 за цю відповідь. Я думаю, що важливо зосередити більше ресурсів на одному пакеті статистичних даних. statsmodelsбуде хорошим вибором.
Ken T

20

Якщо вам потрібно зробити графік QQ одного зразка порівняно з іншим, statsmodels включає qqplot_2samples (). Як і Рікі Робінсон у коментарі вище, це те, що я вважаю графіком QQ проти графіку ймовірності, який є зразком проти теоретичного розподілу.

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


11
Ця реалізація qqplot, схоже, не обробляє зразки з різними розмірами, що смішно, оскільки однією з найбільших переваг сюжету QQ є те, що можна порівнювати зразки з різними розмірами ...
Роберт Мюл,

5

Я це придумав. Можливо, ви можете його вдосконалити. Особливо метод генерації квантилів розподілу мені здається громіздким.

Ви можете замінити np.random.normalбудь-який інший розподіл, np.randomщоб порівняти дані з іншими розподілами.

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

Щоб додати плутанини навколо графіків QQ та графіків ймовірностей у світах Python та R, ось що сказано в посібнику SciPy :

" probplotгенерує графік ймовірності, який не слід плутати з QQ або графіком PP. Statsmodels має більш широкі функціональні можливості цього типу, див. statsmodels.api.ProbPlot."

Якщо ви спробуєте scipy.stats.probplot, то побачите, що він справді порівнює набір даних із теоретичним розподілом. Графіки QQ, OTOH, порівнюють два набори даних (вибірки).

R має функції qqnorm, qqplotі qqline. З довідки R (версія 3.6.3):

qqnormє загальною функцією, метод якої за замовчуванням виробляє нормальний графік QQ значень у. qqlineдодає рядок до «теоретичного», за замовчуванням нормального, квантильно-квантильного графіку, який проходить через зонди квантилей, за замовчуванням першого та третього квартилів.

qqplot створює графік QQ з двох наборів даних.

Коротше кажучи, R qqnormпропонує ту саму функціональність, яка scipy.stats.probplotнадається за замовчуванням dist=norm. Але той факт, що вони назвали це qqnormі що він повинен створювати нормальний графік QQ, може легко заплутати користувачів.

Нарешті, слово попередження. Ці графіки не замінюють належного статистичного тестування і повинні використовуватися лише для ілюстративних цілей.


2

Наскільки великий ваш зразок? Ось ще один варіант перевірки ваших даних на будь-який розподіл за допомогою бібліотеки OpenTURNS . У наведеному нижче прикладі я генерую зразок x з 1 000 000 чисел з уніфікованого розподілу та перевіряю його на нормальний розподіл. Ви можете замінити x своїми даними, якщо переформатувати його якx= [[x1], [x2], .., [xn]]

import openturns as ot

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

У своєму блокноті Юпітера я бачу: введіть тут опис зображення

Якщо ви пишете сценарій, ви можете зробити це більш правильно

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

1

Можна використовувати боке

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

Тут probplot намалюйте графік вимірювань проти нормального розподілу, який вказується в dist = "norm"

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.