使用SciPy的分位数图


84

您将如何使用Python创建一个qq图?

假设您有大量的测量值,并且正在使用一些将XY值作为输入的绘图功能。该函数应将测量的分位数与某种分布的相应分位数(正态,均匀...)作图。

结果图使我们可以评估测量是否遵循假设的分布。

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

R和Matlab都为此提供了现成的函数,但是我想知道用Python实现的最干净的方法是什么。



1
qqplot和probplots有很多选项:statsmodels.sourceforge.net/devel/…–
Josef

Answers:


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
Ricky Robinson

7
@RickyRobinson似乎许多资料(包括维基百科)都与NIST手册相抵触。几乎所有其他来源都指出,QQ图在水平轴上具有理论分位数,在垂直方向上具有数据分位数。无论如何,区别是学术上的:绘制样本基本上与使用经验分布函数相同。无论哪种方式,您都将一个分配的分位数绘制到另一个。
彼得

1
我同意@RickyRobinson,这不是此问题的正确答案。QQ图和概率图虽然在一个分布的分位数与另一个分布之间却有所不同。
佛罗伦萨

48

使用qqplotofstatsmodels.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有人故意分开scipystatsmodels
SARose

3
请注意。您的示例画出了标准正态分布的界线。要像@Geoff示例中那样获得标准化线(按给定样本的标准偏差缩放并添加均值),则需要设置line ='s'而不是line = '45'–
Mike

为此答案+1。我认为将更多的资源集中在一个统计包上非常重要。statsmodels将是一个不错的选择。
肯T

20

如果需要对一个样本与另一个样本进行QQ图绘制,则statsmodels包括qqplot_2samples()。就像上面评论中的Ricky Robinson一样,这就是我认为的QQ图与概率图,这是相对于理论分布的样本。

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


11
这种qqplot实现似乎无法处理大小不同的样本,这很有趣,因为QQ图的最大优势之一是可以比较大小不同的样本……
Robert Muil 2014年

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
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”中指定的图形测量值与正态分布的关系


2

为了增加对Python和R世界中QQ图和概率图的困惑,这是SciPy手册所说的内容:

probplot生成概率图,不应与QQ或PP图混淆。Statsmodels具有此类更广泛的功能,请参阅statsmodels.api.ProbPlot。”

如果尝试一下scipy.stats.probplot,您会发现它确实将数据集与理论分布进行了比较。QQ图OTOH比较两个数据集(样本)。

R具有功能qqnormqqplotqqline。从R帮助(版本3.6.3)中:

qqnorm是一个泛型函数,其默认方法会生成y中值的普通QQ图。qqline在“理论”(默认情况下,正常,分位数-分位数)图中添加一条线,该图通过概率分位数,默认情况下通过第一和第三四分位数。

qqplot 生成两个数据集的QQ图。

简而言之,Rqqnorm提供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

您的样本量是多少?这是使用OpenTURNS库针对任何分布测试数据的另一种选择。在下面的示例中,我从均匀分布中生成了一个1.000.000数字的样本x,并针对正态分布对其进行了测试。如果将x重塑为数据,则可以用数据替换xx= [[x1], [x2], .., [xn]]

import openturns as ot

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

在我的Jupyter笔记本中,我看到: 在此处输入图片说明

如果您正在编写脚本,则可以更正确地执行

from openturns.viewer import View`
import matplotlib.pyplot as plt
View(g)
plt.show()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.