matplotlib/mpl-probscale

Help on modifying weibull probability plot script to utilize probscale

pybokeh opened this issue · 3 comments

Hi, just saw this project and realized I have this old script that makes a Weibull plot and has the y axis as a probability scale using a function that I now forgot how it works. So I thought it would be great if I can replace the y-axis formatter with probscale! But, I am having trouble trying to apply your probscale to the y axis, instead of the function. I would greatly appreciate if someone could modify my script to utilize probscale. Thanks!

Here's my script:

%matplotlib inline
from numpy import *
from matplotlib.ticker import FuncFormatter
import matplotlib.pyplot as plt

# I'm used to  the ln notation for the natural log
from numpy import log as ln

# Paramters
beta = 5.2
eta = 12

# Genrate 10 numbers following a Weibull distribution
x = eta *random.weibull(beta, size=10)
F = 1 - exp( -(x/eta)**beta )

# Estimate Weibull parameters
lnX = ln(x)
lnF = ln( -ln(1-F) )
a, b = polyfit(lnF, lnX, 1)
beta0 = 1/a
eta0  = exp(b)

# ideal line
F0 = array([1e-3, 1-1e-3])
x0 = eta0 * (-ln(1-F0))**(1/beta0)
lnF0 = ln(-ln(1-F0))


# Weibull plot
fig, ax = plt.subplots(figsize=(8, 7))
ax.set_xscale('log')
plt.plot(x, lnF, "bs")
plt.plot(x0, lnF0, 'r-', label="beta= %5G\neta = %.5G" % (beta0, eta0) )
plt.title("Weibull Probability Plot")
plt.grid()
plt.xlabel('x')
plt.ylabel('Cumulative Distribution Function')
plt.legend(loc='lower right')

# ticks
def weibull_CDF(y, pos):
    return "%G %%" % (100*(1-exp(-exp(y))))

formatter = FuncFormatter(weibull_CDF)
ax.yaxis.set_major_formatter(formatter)

yt_F = array([ 0.01, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5,
           0.6, 0.7, 0.8, 0.9, 0.95, 0.99])
yt_lnF = ln( -ln(1-yt_F))
plt.yticks(yt_lnF)

plt.show()

Here's the gist of the script and what the plot looks like.

There are two things you could be talking about here:

  1. is using a weibull_min distirbution to create a probabilty scale
  2. is using Weibull's method of computing plotting positions.

This demonstrates how to do (1):

fig, axes = pyplot.subplots(figsize=(4, 8), ncols=3)

for ax in axes:
    ax.set_ylim(bottom=0.2, top=99.8)
    ax.set_xticks([])
    ax.yaxis.tick_left()
    for side in ['bottom', 'right', 'top']:
        ax.spines[side].set_visible(False)

axes[0].set_ylabel('Linear Scale')

axes[1].set_yscale('prob')
axes[1].set_ylabel('Normal Prob Scale')

axes[2].set_yscale('prob', dist=stats.weibull_min(2))
axes[2].set_ylabel('Weibull Prob Scale')

fig.tight_layout()

capture

This demonstrates how to do either (1) or (2):

data = numpy.random.normal(size=37)
weibull = stats.weibull_min(2)

fig, axes = pyplot.subplots(figsize=(6, 8), nrows=2, ncols=2, sharex=True, sharey='row')

w_probs, w_data = probscale.plot_pos(data, postype='weibull')
n_probs, n_data = probscale.plot_pos(data, postype='cunnane')

w_probs *= 100
n_probs *= 100

axes[0, 0].plot(w_data, w_probs, 'k.')
axes[0, 0].set_yscale('prob', dist=weibull)

axes[1, 0].plot(w_data, w_probs, 'k.')
axes[1, 0].set_yscale('prob')

axes[0, 1].plot(n_data, n_probs, 'k.')
axes[0, 1].set_yscale('prob', dist=weibull)

axes[1, 1].plot(n_data, n_probs, 'k.')
axes[1, 1].set_yscale('prob')

for ax in axes.ravel():
    ax.set_ylim(bottom=1, top=99)
    if ax.is_first_col():
        if ax.is_first_row():
            ax.set_ylabel('Weibull Prob Scale')

        elif ax.is_last_row():
            ax.set_ylabel('Normal Prob Scale')

    if ax.is_first_row():
        if ax.is_first_col():
            ax.set_title('Weibull Plotting Positions')
        elif ax.is_last_col():
            ax.set_title('Normal Plotting Positions')

fig.tight_layout()

download

Thanks @phobson ! This is awesome stuff.