Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inverse probability density function

What do I have to use to figure out the inverse probability density function for normal distribution? I'm using scipy to find out normal distribution probability density function:

from scipy.stats import norm
norm.pdf(1000, loc=1040, scale=210)
0.0018655737107410499

How can I figure out that 0.0018 probability corresponds to 1000 in the given normal distribution?

like image 979
Soid Avatar asked Mar 20 '23 07:03

Soid


2 Answers

There can be no 1:1 mapping from probability density to quantile.

enter image description here

Because the PDF of the normal distribution is quadratic, there can be either 2, 1 or zero quantiles that have a particular probability density.

Update

It's actually not that hard to find the roots analytically. The PDF of a normal distribution is given by:

enter image description here

With a bit of rearrangement we get:

(x - mu)**2 = -2 * sigma**2 * log( pd * sigma * sqrt(2 * pi))

If the discriminant on the RHS is < 0, there are no real roots. If it equals zero, there is a single root (where x = mu), and where it is > 0 there are two roots.

To put it all together into a function:

import numpy as np

def get_quantiles(pd, mu, sigma):

    discrim = -2 * sigma**2 * np.log(pd * sigma * np.sqrt(2 * np.pi))

    # no real roots
    if discrim < 0:
        return None

    # one root, where x == mu
    elif discrim == 0:
        return mu

    # two roots
    else:
        return mu - np.sqrt(discrim), mu + np.sqrt(discrim)

This gives the desired quantile(s), to within rounding error:

from scipy.stats import norm
pd = norm.pdf(1000, loc=1040, scale=210)
print get_quantiles(pd, 1040, 210)
# (1000.0000000000001, 1079.9999999999998)
like image 92
ali_m Avatar answered Apr 07 '23 08:04

ali_m


import scipy.stats as stats
import scipy.optimize as optimize
norm = stats.norm(loc=1040, scale=210)
y = norm.pdf(1000)
print(y)
# 0.00186557371074

print(optimize.fsolve(lambda x:norm.pdf(x)-y, norm.mean()-norm.std()))
# [ 1000.]
print(optimize.fsolve(lambda x:norm.pdf(x)-y, norm.mean()+norm.std()))
# [ 1080.]

There exist distributions which attain any value an infinite number of times. (For example, the simple function with value 1 on an infinite sequence of intervals with lengths 1/2, 1/4, 1/8, etc. attains the value 1 an infinite number of times. And it is a distribution since 1/2 + 1/4 + 1/8 + ... = 1)

So the use of fsolve above is not guaranteed to find all values of x where pdf(x) equals a certain value, but it may help you find some root.

like image 38
unutbu Avatar answered Apr 07 '23 08:04

unutbu