mpl-probscale 入门

安装

mpl-probscale 是在 Python 3.6 上开发的。它也在 Python 3.4、3.5 甚至 2.7(暂时)上进行了测试。

从 conda 安装

mpl-probscale 的官方版本可以在 conda-forge 上找到

conda install --channel=conda-forge mpl-probscale

我的频道上提供了相当新的开发版本构建

conda install --channel=conda-forge mpl-probscale

从 PyPI 安装

官方源代码版本也可以在 PyPI 上找到 pip install probscale

从源代码安装

mpl-probscale 是一个纯 Python 包。在任何平台上从源代码安装都应该非常简单。为此,请从 github 下载或克隆,如有必要解压存档,然后执行

cd mpl-probscale # or wherever the setup.py got placed
pip install .

我推荐使用 pip install . 而不是 python setup.py install,原因见我不完全理解的原因

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

背景

内置 matplotlib 刻度

对于普通用户,您可以将 matplotlib 刻度设置为“linear”(线性)或“log”(对数)。还有其他的(例如,logit,symlog),但我很少在实际应用中看到它们。

线性刻度是默认的

fig, ax = pyplot.subplots()
seaborn.despine(fig=fig)
../_images/output_4_01.png

当您的数据跨越几个数量级且不必以 10 为底时,对数刻度可以很好地工作。

fig, (ax1, ax2) = pyplot.subplots(nrows=2, figsize=(8,3))
ax1.set_xscale('log')
ax1.set_xlim(left=1e-3, right=1e3)
ax1.set_xlabel("Base 10")
ax1.set_yticks([])

ax2.set_xscale('log', basex=2)
ax2.set_xlim(left=2**-3, right=2**3)
ax2.set_xlabel("Base 2")
ax2.set_yticks([])

seaborn.despine(fig=fig, left=True)
../_images/output_6_01.png

概率刻度

mpl-probscale 允许您使用概率刻度。您只需要导入它即可。

在导入之前,matplotlib 中没有可用的概率刻度

try:
    fig, ax = pyplot.subplots()
    ax.set_xscale('prob')
except ValueError as e:
    pyplot.close(fig)
    print(e)
Unknown scale type 'prob'

要访问概率刻度,只需导入 probscale 模块。

import probscale
fig, ax = pyplot.subplots(figsize=(8, 3))
ax.set_xscale('prob')
ax.set_xlim(left=0.5, right=99.5)
ax.set_xlabel('Normal probability scale (%)')
seaborn.despine(fig=fig)
../_images/output_11_01.png

概率刻度默认为标准正态分布(请注意,格式是基于百分比的概率)

您甚至可以使用不同的概率分布,但这可能有点棘手。您必须将 scipy.statsparamnormal 中冻结的分布传递给 ax.set_[x|y]scale 中的 dist kwarg。

这是一个标准正态刻度,带有两个不同的 beta 刻度和一个用于比较的线性刻度。

fig, (ax1, ax2, ax3, ax4) = pyplot.subplots(figsize=(9, 5), nrows=4)

for ax in [ax1, ax2, ax3, ax4]:
    ax.set_xlim(left=2, right=98)
    ax.set_yticks([])

ax1.set_xscale('prob')
ax1.set_xlabel('Normal probability scale, as percents')

beta1 = stats.beta(a=3, b=2)
ax2.set_xscale('prob', dist=beta1)
ax2.set_xlabel('Beta probability scale (α=3, β=2)')

beta2 = stats.beta(a=2, b=7)
ax3.set_xscale('prob', dist=beta2)
ax3.set_xlabel('Beta probability scale (α=2, β=7)')

ax4.set_xticks(ax1.get_xticks()[12:-12])
ax4.set_xlabel('Linear scale (for reference)')

seaborn.despine(fig=fig, left=True)
../_images/output_13_01.png

现成的概率图

mpl-probscale 附带一个小的 viz 模块,可以帮助您创建样本的概率图。

仅使用样本数据,probscale.probplot 将创建一个图形,计算绘图位置和非超越概率,并绘制所有内容

numpy.random.seed(0)
sample = numpy.random.normal(loc=4, scale=2, size=37)

fig = probscale.probplot(sample)
seaborn.despine(fig=fig)
../_images/output_15_0.png

如果您想使用 matplotlib 命令直接自定义绘图,则应指定绘图应发生的 matplotlib 轴

fig, ax = pyplot.subplots(figsize=(7, 3))

probscale.probplot(sample, ax=ax)

ax.set_ylabel('Normal Values')
ax.set_xlabel('Non-exceedance probability')
ax.set_xlim(left=1, right=99)
seaborn.despine(fig=fig)
../_images/output_17_0.png

许多其他选项可以直接从 probplot 函数签名访问。

fig, ax = pyplot.subplots(figsize=(3, 7))

numpy.random.seed(0)
new_sample = numpy.random.lognormal(mean=2.0, sigma=0.75, size=37)

probscale.probplot(
    new_sample,
    ax=ax,
    probax='y', # flip the plot
    datascale='log', # scale of the non-probability axis
    bestfit=True, # draw a best-fit line
    estimate_ci=True,
    datalabel='Lognormal Values',  # labels and markers...
    problabel='Non-exceedance probability',
    scatter_kws=dict(marker='d', zorder=2, mew=1.25, mec='w', markersize=10),
    line_kws=dict(color='0.17', linewidth=2.5, zorder=0, alpha=0.75),
)

ax.set_ylim(bottom=1, top=99)
seaborn.despine(fig=fig)
../_images/output_19_0.png

百分位数和分位数图

为了方便起见,您可以使用相同的函数进行百分位数和分位数图。

注意

百分位数和概率轴是针对相同的值绘制的。唯一的区别是“百分位数”绘制在线性刻度上。

fig, (ax1, ax2, ax3) = pyplot.subplots(nrows=3, figsize=(8, 7))

probscale.probplot(sample, ax=ax1, plottype='pp', problabel='Percentiles')
probscale.probplot(sample, ax=ax2, plottype='qq', problabel='Quantiles')
probscale.probplot(sample, ax=ax3, plottype='prob', problabel='Probabilities')

ax2.set_xlim(left=-2.5, right=2.5)
ax3.set_xlim(left=0.5, right=99.5)
fig.tight_layout()
seaborn.despine(fig=fig)
../_images/output_22_01.png

使用 seaborn FacetGrids

好消息,大家。probplot 函数通常与 FacetGrids 一起按预期工作。

plot = (
    seaborn.load_dataset("tips")
        .assign(pct=lambda df: 100 * df['tip'] / df['total_bill'])
        .pipe(seaborn.FacetGrid, hue='sex', col='time', row='smoker', margin_titles=True, aspect=1., size=4)
        .map(probscale.probplot, 'pct', bestfit=True, scatter_kws=dict(alpha=0.75), probax='y')
        .add_legend()
        .set_ylabels('Non-Exceedance Probabilty')
        .set_xlabels('Tips as percent of total bill')
        .set(ylim=(0.5, 99.5), xlim=(0, 100))
)
../_images/output_24_0.png