Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Finding Probability Distribution Parameters from Percentiles

, 26 Jun 2014 Public Domain
How to determine the parameters of a probability distribution given two percentile constraints
parameter_percentile.zip
parameter_percentile_src.zip
from scipy import stats, optimize
from math import log, pow
from functools import partial

def normal_parameters(x1, p1, x2, p2):
    "Find parameters for a normal random variable X so that P(X < x1) = p1 and P(X < x2) = p2."
    denom = stats.norm.ppf(p2) - stats.norm.ppf(p1)
    sigma = (x2 - x1) / denom
    mu = (x1*stats.norm.ppf(p2) - x2*stats.norm.ppf(p1)) / denom
    return (mu, sigma)
    
def cauchy_parameters(x1, p1, x2, p2):    
    "Find parameters for a Cauchy random variable X so that P(X < x1) = p1 and P(X < x2) = p2."
    denom = stats.cauchy.ppf(p2) - stats.cauchy.ppf(p1)
    sigma = (x2 - x1) / denom
    mu = (x1*stats.cauchy.ppf(p2) - x2*stats.cauchy.ppf(p1)) / denom
    return (mu, sigma)
	
def weibull_parameters(x1, p1, x2, p2):
    "Find parameters for a Weibull random variable X so that P(X < x1) = p1 and P(X < x2) = p2."
    gamma = (log(-log(1-p2)) - log(-log(1-p1))) / (log(x2) - log(x1))
    beta = x1 / pow(-log(1-p1), 1.0/gamma)	
    return (gamma, beta)
    
def gamma_parameters(x1, p1, x2, p2):
    "Find parameters for a gamma random variable X so that P(X < x1) = p1 and P(X < x2) = p2."
    
    # Standardize so that x1 < x2 and p1 < p2
    if p1 > p2:
        (p1, p2) = (p2, p1)
        (x1, x2) = (x2, x1)
    
    # function to find roots of for gamma distribution parameters
    def gamma_aux(p1, p2, target, alpha):
        return stats.gamma.ppf(p2, alpha) / stats.gamma.ppf(p1, alpha) - target
    
    objective = partial( gamma_aux, p1, p2, x2/x1 )
    # The objective function we're wanting to find a root of is decreasing.
    # We need to find an inverval over which is goes from positive to negative.
    left = right = 1.0
    while objective(left) < 0.0:
        left /= 2
    while objective(right) > 0.0:
        right *= 2
    alpha = optimize.bisect(objective, left, right)
    beta = x1 / stats.gamma.ppf(p1, alpha)
    return (alpha, beta)
    
def inverse_gamma_parameters(x1, p1, x2, p2):
    (shape, scale) = gamma_parameters(1/x1, 1-p1, 1/x2, 1-p2)
    return (shape, 1/scale)


	
def test():
    #--------------------------------------------------------------------------
    # Normal distribution
	# Make up a problem.
    p1 = 0.2
    p2 = 0.8
    mu = -3.4
    sigma = 5.6
    x1 = stats.norm.ppf(p1, mu, sigma)
    x2 = stats.norm.ppf(p2, mu, sigma)
    print "Testing normal distribution"
    print "True parameters:       ", mu, sigma
    # Now solve the problem to make sure you get the original parameters back.
    (mu, sigma) = normal_parameters(x1, p1, x2, p2)
    print "Calculated parameters: ", mu, sigma
    print
   
    #--------------------------------------------------------------------------
    # Cauchy distribution
	# Make up a problem.
    p1 = 0.1
    p2 = 0.75
    mu = -3.4
    sigma = 5.6
    x1 = stats.cauchy.ppf(p1, mu, sigma)
    x2 = stats.cauchy.ppf(p2, mu, sigma)
    print "Testing Cauchy distribution"
    print "True parameters:       ", mu, sigma
    # Now solve the problem to make sure you get the original parameters back.
    (mu, sigma) = cauchy_parameters(x1, p1, x2, p2)
    print "Calculated parameters: ", mu, sigma
    print
       
    #--------------------------------------------------------------------------
    # Weibull distribution
	# Make up a problem.
    p1 = 0.2
    p2 = 0.95
    gamma = 2.1
    beta = 3.7
    x1 = stats.exponweib.ppf(p1, 1, gamma, scale=beta)
    x2 = stats.exponweib.ppf(p2, 1, gamma, scale=beta)
    print "Testing Weibull distribution"
    print "True parameters:       ", gamma, beta
    # Now solve the problem to make sure you get the original parameters back.
    (gamma, beta) = weibull_parameters(x1, p1, x2, p2)
    print "Calculated parameters: ", gamma, beta
    print 
    
    #--------------------------------------------------------------------------
    # Gamma distribution
	# Make up a problem.
    p1 = 0.2
    p2 = 0.87
    alpha = 0.4
    beta = 0.86
    
    x1 = stats.gamma.ppf(p1, alpha, scale=beta)
    x2 = stats.gamma.ppf(p2, alpha, scale=beta)
    print "Testing gamma distribution"
    print "True parameters:       ", alpha, beta
    # Now solve the problem to make sure you get the original parameters back.
    (alpha, beta) = gamma_parameters(x1, p1, x2, p2)
    print "Calculated parameters: ", alpha, beta
    print     

    #--------------------------------------------------------------------------
    # Inverse gamma distribution
	# Make up a problem.
    p1 = 0.01
    p2 = 0.38
    alpha = 3.4
    beta = 5.6
    x1 = stats.invgamma.ppf(p1, alpha, scale=beta)
    x2 = stats.invgamma.ppf(p2, alpha, scale=beta)
    print "Testing inverse gamma distribution"
    print "True parameters:       ", alpha, beta
    # Now solve the problem to make sure you get the original parameters back.
    (alpha, beta) = inverse_gamma_parameters(x1, p1, x2, p2)
    print "Calculated parameters: ", alpha, beta
    print    
    
if __name__ == "__main__":
    test()

	

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication

Share

About the Author

John D. Cook

United States United States
I am an independent consultant in software development and applied mathematics. I help companies learn from their data to make better decisions.
 
Check out my blog or send me a note.
 

 

Follow on   Twitter   Google+   LinkedIn

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 26 Jun 2014
Article Copyright 2010 by John D. Cook
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid