使用不同的绘图位置公式

计算绘图位置

当绘制百分位数、分位数或概率图时,必须计算有序数据的绘图位置。

对于总体大小为 \(n\) 的样本 \(X\),第 \(j^\mathrm{th}\) 个元素的绘图位置定义为

\[\frac{x_{j} - \alpha}{n + 1 - \alpha - \beta }\]

在这个公式中,α 和 β 可以取几个值。常见值如下所述

“类型 4” (α=0, β=1)
经验 CDF 的线性插值。
“类型 5” 或 “hazen” (α=0.5, β=0.5)
分段线性插值。
“类型 6” 或 “weibull” (α=0, β=0)
威布尔绘图位置。所有分布的无偏超越概率。推荐用于水文应用。
“类型 7” (α=1, β=1)
R 中的默认值。不建议与概率尺度一起使用,因为最小和最大数据点的绘图位置分别为 0 和 1,因此无法显示。
“类型 8” (α=1/3, β=1/3)
近似中值无偏。
“类型 9” 或 “blom” (α=0.375, β=0.375)
如果数据呈正态分布,则近似无偏位置。
“中位数” (α=0.3175, β=0.3175)
所有分布的中值超越概率(在 scipy.stats.probplot 中使用)。
“apl” 或 “pwm” (α=0.35, β=0.35)
与概率加权矩一起使用。
“cunnane” (α=0.4, β=0.4)
对于正态分布数据,接近无偏分位数。这是默认值。
“gringorten” (α=0.44, β=0.44)
用于耿贝尔分布。

本教程的目的是展示所选的 α 和 β 如何改变概率图的形状。

首先,让我们先完成一些分析设置...

%matplotlib inline
import warnings
warnings.simplefilter('ignore')

import numpy
from matplotlib import pyplot
from scipy import stats
import seaborn

clear_bkgd = {'axes.facecolor':'none', 'figure.facecolor':'none'}
seaborn.set(style='ticks', context='talk', color_codes=True, rc=clear_bkgd)

import probscale


def format_axes(ax1, ax2):
    """ Sets axes labels and grids """
    for ax in (ax1, ax2):
        if ax is not None:
            ax.set_ylim(bottom=1, top=99)
            ax.set_xlabel('Values of Data')
            seaborn.despine(ax=ax)
            ax.yaxis.grid(True)

    ax1.legend(loc='upper left', numpoints=1, frameon=False)
    ax1.set_ylabel('Normal Probability Scale')
    if ax2 is not None:
        ax2.set_ylabel('Weibull Probability Scale')

正态 vs 威布尔尺度和 Cunnane vs 威布尔绘图位置

在这里,我们将生成一些伪造的正态分布数据,并从 scipy 定义一个威布尔分布,用于概率尺度。

numpy.random.seed(0)  # reproducible
data = numpy.random.normal(loc=5, scale=1.25, size=37)

# simple weibull distribution
weibull = stats.weibull_min(2)

现在,让我们在威布尔和正态概率尺度上创建概率图。此外,我们将为每个图以两种不同的常用方式计算绘图位置。

首先,在蓝色圆圈中,我们将显示具有威布尔 (α=0, β=0) 绘图位置的数据。威布尔绘图位置通常用于水文和水资源工程等领域。

在绿色方块中,我们将使用 Cunnane (α=0.4, β=0.4) 绘图位置。Cunnane 绘图位置适用于正态分布数据,是默认值。

w_opts = {'label': 'Weibull (α=0, β=0)',     'marker': 'o', 'markeredgecolor': 'b'}
c_opts = {'label': 'Cunnane (α=0.4, β=0.4)', 'marker': 's', 'markeredgecolor': 'g'}

common_opts = {
    'markerfacecolor': 'none',
    'markeredgewidth': 1.25,
    'linestyle': 'none'
}

fig, (ax1, ax2) = pyplot.subplots(figsize=(10, 8), ncols=2, sharex=True, sharey=False)

for dist, ax in zip([None, weibull], [ax1, ax2]):
    for opts, postype in zip([w_opts, c_opts,], ['weibull', 'cunnane']):
        probscale.probplot(data, ax=ax, dist=dist, probax='y',
                           scatter_kws={**opts, **common_opts},
                           pp_kws={'postype': postype})

format_axes(ax1, ax2)
fig.tight_layout()
../_images/output_9_0.png

这表明绘图位置的不同公式在数据集的极端值处变化最大。

Hazen 绘图位置

接下来,让我们比较 Hazen/类型 5 (α=0.5, β=0.5) 公式与 Cunnane。Hazen 绘图位置(显示为红色三角形)代表数据集经验累积分布函数的分段线性插值。

鉴于 α 和 β=0.5 的值仅与 Cunnane 值略有不同,绘图位置可预测地相似。

h_opts = {'label': 'Hazen (α=0.5, β=0.5)', 'marker': '^', 'markeredgecolor': 'r'}
fig, (ax1, ax2) = pyplot.subplots(figsize=(10, 8), ncols=2, sharex=True, sharey=False)

for dist, ax in zip([None, weibull], [ax1, ax2]):
    for opts, postype in zip([c_opts, h_opts,], ['cunnane', 'Hazen']):
        probscale.probplot(data, ax=ax, dist=dist, probax='y',
                           scatter_kws={**opts, **common_opts},
                           pp_kws={'postype': postype})

format_axes(ax1, ax2)
fig.tight_layout()
../_images/output_11_0.png

总结

冒着展示一个非常混乱且难以阅读的图形的风险,让我们将所有三个放在同一个正态概率尺度上

fig, ax1 = pyplot.subplots(figsize=(6, 8))

for opts, postype in zip([w_opts, c_opts, h_opts,], ['weibull', 'cunnane', 'hazen']):
    probscale.probplot(data, ax=ax1, dist=None, probax='y',
                       scatter_kws={**opts, **common_opts},
                       pp_kws={'postype': postype})

format_axes(ax1, None)
fig.tight_layout()
../_images/output_13_0.png

同样,α 和 β 的不同值不会显着改变概率图在 – 比方说 – 下四分位数和上四分位数之间的形状。然而,在四分位数之外,差异更加明显。

下面的单元格使用我们研究过的三组 α 和 β 值计算绘图位置,并打印前十个值以便于比较。

# weibull plotting positions and sorted data
w_probs, _ = probscale.plot_pos(data, postype='weibull')

# normal plotting positions, returned "data" is identical to above
c_probs, _ = probscale.plot_pos(data, postype='cunnane')

# type 4 plot positions
h_probs, _ = probscale.plot_pos(data, postype='hazen')

# convert to percentages
w_probs *= 100
c_probs *= 100
h_probs *= 100

print('Weibull: ', numpy.round(w_probs[:10], 2))
print('Cunnane: ', numpy.round(c_probs[:10], 2))
print('Hazen:   ', numpy.round(h_probs[:10], 2))
Weibull:  [  2.63   5.26   7.89  10.53  13.16  15.79  18.42  21.05  23.68  26.32]
Cunnane:  [  1.61   4.3    6.99   9.68  12.37  15.05  17.74  20.43  23.12  25.81]
Hazen:    [  1.35   4.05   6.76   9.46  12.16  14.86  17.57  20.27  22.97  25.68]