How to calculate the inverse of the normal cumulative distribution function in python?

151,469

Solution 1

NORMSINV (mentioned in a comment) is the inverse of the CDF of the standard normal distribution. Using scipy, you can compute this with the ppf method of the scipy.stats.norm object. The acronym ppf stands for percent point function, which is another name for the quantile function.

In [20]: from scipy.stats import norm

In [21]: norm.ppf(0.95)
Out[21]: 1.6448536269514722

Check that it is the inverse of the CDF:

In [34]: norm.cdf(norm.ppf(0.95))
Out[34]: 0.94999999999999996

By default, norm.ppf uses mean=0 and stddev=1, which is the "standard" normal distribution. You can use a different mean and standard deviation by specifying the loc and scale arguments, respectively.

In [35]: norm.ppf(0.95, loc=10, scale=2)
Out[35]: 13.289707253902945

If you look at the source code for scipy.stats.norm, you'll find that the ppf method ultimately calls scipy.special.ndtri. So to compute the inverse of the CDF of the standard normal distribution, you could use that function directly:

In [43]: from scipy.special import ndtri

In [44]: ndtri(0.95)
Out[44]: 1.6448536269514722

Solution 2

Starting Python 3.8, the standard library provides the NormalDist object as part of the statistics module.

It can be used to get the inverse cumulative distribution function (inv_cdf - inverse of the cdf), also known as the quantile function or the percent-point function for a given mean (mu) and standard deviation (sigma):

from statistics import NormalDist

NormalDist(mu=10, sigma=2).inv_cdf(0.95)
# 13.289707253902943

Which can be simplified for the standard normal distribution (mu = 0 and sigma = 1):

NormalDist().inv_cdf(0.95)
# 1.6448536269514715

Solution 3

# given random variable X (house price) with population muy = 60, sigma = 40
import scipy as sc
import scipy.stats as sct
sc.version.full_version # 0.15.1

#a. Find P(X<50)
sct.norm.cdf(x=50,loc=60,scale=40) # 0.4012936743170763

#b. Find P(X>=50)
sct.norm.sf(x=50,loc=60,scale=40) # 0.5987063256829237

#c. Find P(60<=X<=80)
sct.norm.cdf(x=80,loc=60,scale=40) - sct.norm.cdf(x=60,loc=60,scale=40)

#d. how much top most 5% expensive house cost at least? or find x where P(X>=x) = 0.05
sct.norm.isf(q=0.05,loc=60,scale=40)

#e. how much top most 5% cheapest house cost at least? or find x where P(X<=x) = 0.05
sct.norm.ppf(q=0.05,loc=60,scale=40)
Share:
151,469

Related videos on Youtube

Yueyoum
Author by

Yueyoum

Updated on July 08, 2022

Comments

  • Yueyoum
    Yueyoum almost 2 years

    How do I calculate the inverse of the cumulative distribution function (CDF) of the normal distribution in Python?

    Which library should I use? Possibly scipy?

    • Warren Weckesser
      Warren Weckesser over 10 years
      Do you mean the inverse Gaussian distribution (en.wikipedia.org/wiki/Inverse_Gaussian_distribution), or the inverse of the cumulative distribution function of the normal distribution (en.wikipedia.org/wiki/Normal_distribution), or something else?
    • Yueyoum
      Yueyoum over 10 years
      @WarrenWeckesser the second one: inverse of the cumulative distribution function of the normal distribution
    • Yueyoum
      Yueyoum over 10 years
      @WarrenWeckesser i mean the python version of "normsinv" function in excel.
  • William Zhang
    William Zhang over 9 years
    I always think "percent point function" (ppf) is a terrible name. Most people in statistics just use "quantile function".
  • Suresh2692
    Suresh2692 almost 7 years
    PS: You can assume 'loc' as 'mean' and 'scale' as 'standard deviation'
  • Jethro Cao
    Jethro Cao about 4 years
    Great tip! This allows me to drop the dependency on scipy, which I needed just for the single stats.norm.ppf method
  • bones.felipe
    bones.felipe over 3 years
    Don't you need to specify the mean and the std on both ppf and cdf?
  • Warren Weckesser
    Warren Weckesser over 3 years
    @bones.felipe, the "standard" normal distribution has mean 0 and standard deviation 1. These are the default values for the location and scale of the scipy.stats.norm methods.
  • bones.felipe
    bones.felipe over 3 years
    Right, I thought I saw this norm.cdf(norm.ppf(0.95, loc=10, scale=2)) and I thought it was weird norm.cdf did not have loc=10 and scale=2 too, I guess it should.
  • vanetoj
    vanetoj about 2 years
    can you use that to transform data with uniform distribution to normal ?