The Normal and Binomial distributions, explained with Python
Tags: datascience, python, beginners, tutorial
Published: 2022-05-16 19:25:40

*(Originally published on [darrendube.com](https://darrendube.com/blog/data-science/normal-distribution-in-python/)).*

***

The Binomial and Normal (or Gaussian) distributions are some of the most common distributions in Statistics. They are used anywhere from predicting movements in stock prices, to grading SAT tests. As an introduction to data visualisation in python, we will be plotting a binomial distribution, then plotting a normal estimation to the binomial.

(If you've only come for the visualisation part, skip to [this point](#plotting-the-binomial-distribution))

## What are the Normal and Binomial Distributions

Even if you didn’t take a high school statistics class, you’ve probably still encountered the Gaussian (or normal) distribution in a math or science class.

If you created a histogram to represent the heights of people in a class, it would likely create a bell curve, with the more common heights in the middle, and the less common ones on the sides.

![Histogram of heights of people in a class](https://d1hj4to4g9ba46.cloudfront.net/questions/460828.PNG "Source: toppr.com")

If you increased the number of subjects in your sample, the graph would more and more closely resemble the shape of a normal distribution:

![Graph of 14 year olds' heights](https://i0.wp.com/statisticsbyjim.com/wp-content/uploads/2018/04/probability_distribution_heights.png?w=576&ssl=1 "Source: statisticsbyjim.com")

The probability distribution function of a normal distribution is :

{% katex %}
f(x) = \frac{1}{\sigma\sqrt{2\pi}}
e^{ -\frac{1}{2}\left(\frac{x-\mu}{\sigma}\right)^{\!2}\,}
{% endkatex %}

The shape of the graph is determined by its [mean](https://en.wikipedia.org/wiki/Mean) and [standard deviation](https://en.wikipedia.org/wiki/Standard_deviation). The graph is **centred** around the mean, and the standard deviation determines how **stretched** it is in the x-direction.

Besides the heights of people in a class, many other random variables follow the normal distributions, including measurement error, SAT scores, and shoe sizes. The area under two points on the graph, divided by the area of the whole graph, gives the probability of a value between those two points.

Closely related is the **binomial distribution**. Even if you haven’t heard of it, it is very intuitive to understand.

Consider a coin toss: the probability of hitting either heads or tails is {% katex inline %}0.5{% endkatex %}. If there is a fixed number of trials, the binomial distribution is used to calculate the probability of, e.g., getting {% katex inline %}2{% endkatex %} heads in {% katex inline %}10{% endkatex %} tries. It is represented by the probability density function:

{% katex %}
P_{x}=(nCr) p^{x} (1-p)^{n-x}
{% endkatex %}

meaning, in {% katex inline %}n{% endkatex %} trials, each with a probability {% katex inline %}p{% endkatex %} of success, the probability of getting {% katex inline %}x{% endkatex %} successes is {% katex inline %}P_{x}{% endkatex %}. In the coin toss example, {% katex inline %}n=10{% endkatex %}, {% katex inline %}p=0.5{% endkatex %}, and success means getting heads. While it is possible that there will be no heads in all 10 trials, it is unlikely, hence {% katex inline %}P_{0}{% endkatex %} will be extremely low. Likewise, it is unlikely all 10 tosses will be heads, hence {% katex inline %}P_{10}{% endkatex %} will likely be low too. The more likely number of successes would be in the middle, with the most likely being {% katex inline %}n\times p (=10){% endkatex %}.

If you increase the number of trials, the shape of the graph starts to look very familiar...

![image of binomial distribution](https://www.inchcalculator.com/wp-content/uploads/2021/11/binomial-distribution.png "Source: inchcalculator.com")

If the number of attempts is large enough, the binomial distribution resembles a normal distribution. **This means a normal distribution can be used to estimate the binomial by using {% katex inline %}\mu=np{% endkatex %} and {% katex inline %}\sigma=np(1-p){% endkatex %}.** This is very useful when, for instance, you're trying to find the probability it takes more than 30 tries when {% katex inline %}n=100{% endkatex %} (which would normally require you to find {% katex inline %}P_{x}{% endkatex %} for **every** number from 31-100).

However, there's a catch: the binomial distribution deals with [discrete](https://www.g2.com/articles/discrete-vs-continuous-data) variables (i.e. there is no {% katex inline %}P_{8.443}{% endkatex %} or {% katex inline %}P_{3.142}{% endkatex %}, only whole numbers), whereas the normal distribution deals with continuous variables. This means the normal distribution is only an approximation to the binomial.

I realise this is by no means an exhaustive introduction. If you're still *confused*, [this](https://www.mathsisfun.com/data/standard-normal-distribution.html) and [this](https://www.mathsisfun.com/data/standard-normal-distribution.html) are more in-depth explanations.

## Plotting the binomial distribution

We can plot a graph of the probabilities associated with each number of tries. In this example, I’ll be using Python and [matplotlib](https://matplotlib.org/).

If you do not have `matplotlib` installed on Python yet, install it by typing `pip install matplotlib`.

Begin by importing `matplotlib` and `math`. We'll need `math` to get the value of {% katex inline %}e{% endkatex %}, and the {% katex inline %}nCx{% endkatex %} function.

```python
import math
import matplotlib.pyplot as pyplot
```

Firstly, we need to define the probability density function of the binomial distribution. To recall:

{% katex %}
P_{x}=(nCr) p^{x} (1-p)^{n-x}
{% endkatex %}

In python:

```python
def binomial(x, n, p):
    return math.comb(n, x) * (p ** x) * ((1 - p) ** (n - x))
```

In this case, to make the binomial distribution more clearly resemble a normal distribution, I will make {% katex inline %}n{% endkatex %} equal to {% katex inline %}50{% endkatex %}. {% katex inline %}p{% endkatex %} will be 0.5. We also need to initialise a list to store the 50 values we get from the binomial p.d.f for each value of {% katex inline %}x{% endkatex %}, and another list to store keys (that basically number each value of {% katex inline %}x{% endkatex %} in the previous list).

```python
n = 50
p = 0.5
binomial_list = []
keys = []
```

Now that we have initialised all the variables we need, we can now iterate over each number from {% katex inline %}1{% endkatex %} to {% katex inline %}50{% endkatex %} to get values of {% katex inline %}P_{x}{% endkatex %} for each, and we need to fill the `keys[]` list with numbers from {% katex inline %}1{% endkatex %} to {% katex inline %}50{% endkatex %}:

```python
for x in range(50):
    binomial_list.append(binomial(x, n, p))

for y in range(50):
    keys.append(y)
```

All that's left is to plot the graph!

```python
pyplot.bar(x=keys, height=binomial_list)
pyplot.show()

```

And voila!

![normal distribution](https://i.ibb.co/BThQyS1/Figure-1.png)

As you can see, it clearly resembles a normal distribution. To see if it actually has the shape of a normal distribution, we can superimpose the normal curve by inserting this code (before the `pyplot.show()` expression:

```python
def normal_distribution(x, mu, sigma):
    return (math.exp(-0.5 * ((x - mu) / sigma) ** 2)) / (sigma * math.sqrt(2 * math.pi))

pyplot.plot(keys, [normal_distribution(y, n*p, math.sqrt(n*p*(1-p))) for y in range(50)])
```

![binomial and normal](https://i.ibb.co/RDyzWsB/Figure-1.png)

*(Originally published on [darrendube.com](https://darrendube.com/blog/data-science/normal-distribution-in-python/)).*