Exploring Normal Distribution With Jupyter Notebook | by Shinichi Okada | Towards Data Science

Table of ContentsIntroduction1. Normal Distribution Probability Density Function2. Using random normal distribution values3. A cumulative normal distribution function4. Calculating the probability of normal distribution5. Interval between variables6. Finding quantiles7. Multivariate Normal Distribution8. Standard normal distribution9. Standardized normal variable10. Finding the standard normal valueConclusion
Normal distributions are often used in the natural and social sciences to represent real-valued random variables whose distributions are not known. The Normal distribution is a continuous theoretical probability distribution. In this article, I am going to explore the Normal distribution using Jupyter Notebook.
Let’s import all the necessary libraries.
from scipy.stats import normimport numpy as npimport matplotlib.pyplot as plt
The probability density function (PDF) of the normal distribution is:
The random variable X described by the PDF is a normal variable that follows a normal distribution with mean and variance.
Normal distribution notation is:
The area under the curve equals 1.
norm.pdf returns a PDF value. The following is the PDF value when x=1, μ=0, σ=1.
norm.pdf(x=1.0, loc=0, scale=1)
If you want to see the code for the above graph, please see this.
Since norm.pdf returns a PDF value, we can use this function to plot the normal distribution function. We graph a PDF of the normal distribution using scipy, numpy and matplotlib. We use the domain of −4<x<4, the range of 0<f(x)<0.45, the default values μ=0 and σ=1. plot(x-values,y-values) produces the graph.
fig, ax = plt.subplots()x= np.arange(-4,4,0.001)ax.set_title('N(0,$1^2$)')ax.set_xlabel('x')ax.set_ylabel('f(x)')ax.plot(x, norm.pdf(x))ax.set_ylim(0,0.45)plt.show()
A normal curve is smooth bell-shaped. It is symmetrical about the x=μ and has a maximum point at x=μ.
Let’s plot the probability distribution functions of a normal distribution where the mean has different standard deviations.
scipy.norm.pdf has keywords, loc and scale. The location (loc) keyword specifies the mean and the scale (scale) keyword specifies the standard deviation.
fig, ax = plt.subplots()x = np.linspace(-10,10,100)stdvs = [1.0, 2.0, 3.0, 4.0]for s in stdvs:    ax.plot(x, norm.pdf(x,scale=s), label='stdv=%.1f' % s)    ax.set_xlabel('x')ax.set_ylabel('pdf(x)')ax.set_title('Normal Distribution')ax.legend(loc='best', frameon=True)ax.set_ylim(0,0.45)ax.grid(True)
Let’s plot probability distribution functions of normal distribution where the standard deviation is 1 and different means.
fig, ax = plt.subplots()x = np.linspace(-10,10,100)means = [0.0, 1.0, 2.0, 5.0]for mean in means:    ax.plot(x, norm.pdf(x,loc=mean), label='mean=%.1f' % mean)    ax.set_xlabel('x')ax.set_ylabel('pdf(x)')ax.set_title('Normal Distribution')ax.legend(loc='best', frameon=True)ax.set_ylim(0,0.45)ax.grid(True)
The mean of the distribution determines the location of the center of the graph. As you can see in the above graph, the shape of the graph does not change by changing the mean, but the graph is translated horizontally.
towardsdatascience.com
norm.rvs generates random normal distribution numbers according to the scale which is the standard deviation, the loc which is the mean and the size. We create a histogram for the generated numbers and add the PDF.
fig, ax = plt.subplots()xs = norm.rvs(scale=2,size=1000)x = np.linspace(-10,10,100)p = norm.pdf(x,scale=2)v = np.var(xs)m = np.mean(xs)ax = fig.add_subplot(111)ax.hist(xs, bins=10, alpha=0.5, density=True)ax.plot(x,p, 'r-', lw=2)ax.set_xlabel('x')ax.set_ylabel('pdf(x)')ax.set_title(f'mean={m:.2f}, var={v:.2f}')ax.grid(True)
The cumulative distribution function of a random variable X, evaluated at x, is the probability that X will take a value less than or equal to x. Since the normal distribution is a continuous distribution, the shaded area of the curve represents the probability that X is less or equal than x.
Using fill_between(x, y1, y2=0), it will fill up the area between two curves y1 and y2 which has the default value of 0.
fig, ax = plt.subplots()# for distribution curvex= np.arange(-4,4,0.001)ax.plot(x, norm.pdf(x))ax.set_title("Cumulative normal distribution")ax.set_xlabel('x')ax.set_ylabel('pdf(x)')ax.grid(True)# for fill_betweenpx=np.arange(-4,1,0.01)ax.set_ylim(0,0.5)ax.fill_between(px,norm.pdf(px),alpha=0.5, color='g')# for textax.text(-1,0.1,"cdf(x)", fontsize=20)plt.show()
Given the mean of 3 and the standard deviation of 2, we can find the probability of P(X<2).
In norm.cdf, the location (loc) keyword specifies the mean and the scale (scale) keyword specifies the standard deviation.
from scipy.stats import normlessthan2=norm.cdf(x=2, loc=3, scale=2)print(lessthan2)
Let’s plot a graph.
fig, ax = plt.subplots()# for distribution curvex= np.arange(-4,10,0.001)ax.plot(x, norm.pdf(x,loc=3,scale=2))ax.set_title("N(3,$2^2$)")ax.set_xlabel('x')ax.set_ylabel('pdf(x)')ax.grid(True)# for fill_betweenpx=np.arange(-4,2,0.01)ax.set_ylim(0,0.25)ax.fill_between(px,norm.pdf(px,loc=3,scale=2),alpha=0.5, color='g')# for textax.text(-0.5,0.02,round(lessthan2,2), fontsize=20)plt.show()
To find the probability of an interval between certain variables, you need to subtract cdf from another cdf. Let's find P(0.5<X<2) with a mean of 1 and a standard deviation of 2.
norm(1, 2).cdf(2) - norm(1,2).cdf(0.5)
Here is the graph.
fig, ax = plt.subplots()# for distribution curvex= np.arange(-6,8,0.001)ax.plot(x, norm.pdf(x,loc=1,scale=2))ax.set_title("N(1,$2^2$)")ax.set_xlabel('x')ax.set_ylabel('pdf(x)')ax.grid(True)px=np.arange(0.5,2,0.01)ax.set_ylim(0,0.25)ax.fill_between(px,norm.pdf(px,loc=1,scale=2),alpha=0.5, color='g')pro=norm(1, 2).cdf(2) - norm(1,2).cdf(0.5)ax.text(0.2,0.02,round(pro,2), fontsize=20)plt.show()
To find the probability of P(X>4), we can use sf which is called the survival function and it returns 1-cdf. For example, norm.sf(x=4, loc=3, scale=2 returns the probability which is greater than x=4,P(X>4) when μ=4,σ=2.
gr4sf=norm.sf(x=4, loc=3, scale=2)gr4sf
Let’s plot a graph.
fig, ax = plt.subplots()x= np.arange(-4,10,0.001)ax.plot(x, norm.pdf(x,loc=3,scale=2))ax.set_title("N(3,$2^2$)")ax.set_xlabel('x')ax.set_ylabel('pdf(x)')ax.grid(True)px=np.arange(4,10,0.01)ax.set_ylim(0,0.25)ax.fill_between(px,norm.pdf(px,loc=3,scale=2),alpha=0.5, color='g')ax.text(4.5,0.02,"sf(x) %.2f" %(gr4sf), fontsize=20)plt.show()
The above graph is the same as 1−P(X<4).
gr4=norm.cdf(x=4, loc=3, scale=2)gr14=1-gr4fig, ax = plt.subplots()x= np.arange(-4,10,0.001)ax.plot(x, norm.pdf(x,loc=3,scale=2))ax.set_title("N(3,$2^2$)")ax.set_xlabel('x')ax.set_ylabel('pdf(x)')ax.grid(True)px=np.arange(4,10,0.01)ax.set_ylim(0,0.25)ax.fill_between(px,norm.pdf(px,loc=3,scale=2),alpha=0.5, color='g')px1=np.arange(-4,4,0.01)ax.fill_between(px1,norm.pdf(px1,loc=3,scale=2),alpha=0.5, color='r')ax.text(4.5,0.02,round(gr14,2), fontsize=20)ax.text(1,0.02,round(gr4,2), fontsize=20)plt.show()
towardsdatascience.com
k in P(X≤k)=0.95
is known as quantile, in this case, the 95% quantile.
ppf is the inverse of cdf and it is called the Percent point function. Given the mean of 1 and the standard deviation of 3, we can find the quantile a in P(X<a)=0.506 by using ppf.
norm.ppf(q=0.506, loc=1, scale=3)
Let’s plot a graph.
fig, ax = plt.subplots()x= np.arange(-10,10,0.001)ax.plot(x, norm.pdf(x,loc=1,scale=3))ax.set_title("N(1,$3^2$)")ax.set_xlabel('x')ax.set_ylabel('pdf(x)')ax.grid(True)xpoint=norm.ppf(q=0.506, loc=1, scale=3)px=np.arange(-10,xpoint,0.01)ax.set_ylim(0,0.15)ax.fill_between(px,norm.pdf(px,loc=1,scale=3),alpha=0.5, color='g')ax.text(.8,0.02,"x= %.2f" %xpoint, fontsize=20)ax.text(-5,0.05,"P(X)=0.506", fontsize=20)plt.show()
With the same mean and standard deviation, we can find the quantile b in P(X>b)=0.198 using the inverse survival function isf. This is the same as using ppf with q=(1−0.198).
norm.isf(q=0.198, loc=1, scale=3)
norm.ppf(q=(1-0.198), loc=1, scale=3)
norm.interval returns endpoints of the range that contains the alpha percent of the distribution. For example, with a mean of 0 and a standard deviation of 1 to find 95% of the probability, norm.interval returns x values around the mean, in this case, μ=0.
a,b = norm.interval(alpha=0.95, loc=0, scale=1)print(a,b)
fig, ax = plt.subplots()x= np.arange(-4,4,0.001)ax.plot(x, norm.pdf(x))ax.set_title("Interval")ax.set_xlabel('x')ax.set_ylabel('pdf(x)')ax.grid(True)px=np.arange(a,b,0.01)ax.set_ylim(0,0.5)ax.fill_between(px,norm.pdf(px),alpha=0.5, color='g')ax.text(-0.5,0.1,"0.95", fontsize=20)plt.show()
The multivariate normal distribution is often used to describe any set of correlated real-valued random variables.
We use multivariate_normal which requires the array of mean and covariance matrix. To make it simple, we use a diagonal matrix in which all off-diagonal elements are zero.
from scipy.stats import multivariate_normalx,y = np.meshgrid(np.linspace(-10,10,100),np.linspace(-10,10,100))pos = np.dstack((x,y))mean = np.array([1, 2])cov  = np.array([[3,0],[0,15]])rv = multivariate_normal(mean,cov)z = rv.pdf(pos)fig = plt.figure()ax = fig.add_subplot(111,aspect='equal')ax.contourf(x,y,z)ax.set_xlim(-10,10)ax.set_ylim(-10,10)ax.set_xlabel('x')ax.set_ylabel('y')ax.set_title('pdf')
We can create a 3D graph using matplotlib’s mpl_toolkits.mplot3d.Axes3D. We also use Scipy frozen RV object.
import numpy as npimport matplotlib.pyplot as pltfrom scipy.stats import multivariate_normalfrom mpl_toolkits.mplot3d import Axes3D# Create grid and multivariate normalx = np.linspace(-10,10,500)y = np.linspace(-10,10,500)X, Y = np.meshgrid(x,y)pos = np.empty(X.shape + (2,))pos[:, :, 0] = X pos[:, :, 1] = Y# Create a frozen RV objectmean = np.array([1, 2])cov  = np.array([[3,0],[0,15]])rv = multivariate_normal(mean,cov)# Make a 3D plotfig = plt.figure()ax = fig.gca(projection='3d')ax.plot_surface(X, Y, rv.pdf(pos),cmap='viridis',linewidth=0)ax.set_xlabel('X axis')ax.set_ylabel('Y axis')ax.set_zlabel('Z axis')plt.show()
When μ=0 and variance=1, it is called the standard normal distribution. The above probability function is simplified to:
All normal curves can be related to the standard normal distribution.
To standardize a random variable into the standardized normal variable Z∼N(0,1) we use the transformation:
The standardized value Z tells how many standard deviations below or above the mean the original value is.
For example, to find the standardized value for x=1 when a mean of 2 and a standard deviation of 3.
We can use norm.cdf to find the probability and use norm.ppf with μ=0,σ=1 to find the standardized value.
norm.cdf(1, loc=2, scale=3)
norm.ppf(q=norm.cdf(1, loc=2, scale=3))
scipy.stats.norm gives us parameters such as loc and scale to specifies the standard deviation. It also has a variety of methods and we explored rvs, cdf, sf, ppf, interval, and isf in this article.
Matplotlib gives us easy but extensive tools to change minute details of a figure including 3D.
Get full access to every story on Medium by becoming a member.