График квантиля-квантиля с использованием SciPy


87

Как бы вы создали qq-график с помощью Python?

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

Полученный график позволяет нам затем оценить, следует ли в наших измерениях предполагаемое распределение или нет.

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

И R, и Matlab предоставляют для этого готовые функции, но мне интересно, каким будет самый чистый метод для реализации в Python.



1
qqplot и probplots с множеством опций: statsmodels.sourceforge.net/devel/…
Josef

Ответы:


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

Результат

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


Иногда я видел несколько пунктирных линий уверенности, которые сужаются к середине и напоминают звук трубы на концах. Можете ли вы добавить эти «направляющие линии» к сюжету?
Norfeldt

21
Хорошо, но это вероятностный график (выборка против теоретического распределения). График qq сравнивает два образца. itl.nist.gov/div898/handbook/eda/section3/qqplot.htm itl.nist.gov/div898/handbook/eda/section3/probplot.htm
Рики Робинсон

7
@RickyRobinson Кажется, что многие источники (включая Википедию) противоречат руководству NIST. Практически любой другой источник утверждает, что график QQ имеет теоретические квантили по горизонтальной оси и квантили данных по вертикали. В любом случае, различие носит академический характер: построение выборки по сути то же самое, что и использование эмпирической функции распределения. В любом случае вы строите график квантилей одного распределения относительно другого.
Питер

1
Я согласен с @RickyRobinson, это неправильный ответ на этот вопрос. Графики QQ и вероятностные графики отличаются, даже если они оба являются квантилями одного распределения относительно другого.
Florent

49

Использование 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

5
Просто примечание. В вашем примере проводится линия стандартного нормального распределения. Чтобы получить стандартизированную линию (масштабированную стандартным отклонением данного образца и добавленную среднее значение), как в примере @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 значений y. qqlineдобавляет строку к «теоретическому», по умолчанию нормальному графику квантиль-квантиль, который проходит через квантили вероятностей, по умолчанию первый и третий квартили.

qqplot создает график QQ из двух наборов данных.

Короче говоря, R qqnormпредлагает те же функции, что scipy.stats.probplotи настройки по умолчанию dist=norm. Но тот факт, что они назвали это qqnormи что он должен «производить нормальный график QQ», может легко запутать пользователей.

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


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"


0

Насколько велик ваш образец? Вот еще один вариант тестирования ваших данных на соответствие любому дистрибутиву с использованием библиотеки 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

В моем Jupyter Notebook я вижу: введите описание изображения здесь

Если вы пишете сценарий, вы можете сделать это более правильно

from openturns.viewer import View`
import matplotlib.pyplot as plt
View(g)
plt.show()
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.