# Lambda School Data Science Module 132
## Sampling, Confidence Intervals, and Hypothesis Testing

## Prepare - examine other available hypothesis tests

If you had to pick a single hypothesis test in your toolbox, t-test would probably be the best choice - but the good news is you don't have to pick just one! Here's some of the others to be aware of:

```
import numpy as np
from scipy.stats import chisquare  # One-way chi square test

# Chi square can take any crosstab/table and test the independence of rows/cols
# The null hypothesis is that the rows/cols are independent -> low chi square
# The alternative is that there is a dependence -> high chi square
# Be aware! Chi square does *not* tell you direction/causation

ind_obs = np.array([[1, 1], [2, 2]]).T
print(ind_obs)
print(chisquare(ind_obs, axis=None))

dep_obs = np.array([[16, 18, 16, 14, 12, 12], [32, 24, 16, 28, 20, 24]]).T
print(dep_obs)
print(chisquare(dep_obs, axis=None))
```

    [[1 2]
     [1 2]]
    Power_divergenceResult(statistic=0.6666666666666666, pvalue=0.8810148425137847)
    [[16 32]
     [18 24]
     [16 16]
     [14 28]
     [12 20]
     [12 24]]
    Power_divergenceResult(statistic=23.31034482758621, pvalue=0.015975692534127565)

```
# Distribution tests:
# We often assume that something is normal, but it can be important to *check*

# For example, later on with predictive modeling, a typical assumption is that
# residuals (prediction errors) are normal - checking is a good diagnostic

from scipy.stats import normaltest
# Poisson models arrival times and is related to the binomial (coinflip)
sample = np.random.poisson(5, 1000)
print(normaltest(sample))  # Pretty clearly not normal
```

    NormaltestResult(statistic=28.671707051053502, pvalue=5.94316681668777e-07)

```
# Kruskal-Wallis H-test - compare the median rank between 2+ groups
# Can be applied to ranking decisions/outcomes/recommendations
# The underlying math comes from chi-square distribution, and is best for n>5
from scipy.stats import kruskal

x1 = [1, 3, 5, 7, 9]
y1 = [2, 4, 6, 8, 10]
print(kruskal(x1, y1))  # x1 is a little better, but not "significantly" so

x2 = [1, 1, 1]
y2 = [2, 2, 2]
z = [2, 2]  # Hey, a third group, and of different size!
print(kruskal(x2, y2, z))  # x clearly dominates
```

    KruskalResult(statistic=0.2727272727272734, pvalue=0.6015081344405895)
    KruskalResult(statistic=7.0, pvalue=0.0301973834223185)

And there's many more! `scipy.stats` is fairly comprehensive, though there are even more available if you delve into the extended world of statistics packages. As tests get increasingly obscure and specialized, the importance of knowing them by heart becomes small - but being able to look them up and figure them out when they *are* relevant is still important.

## T-test Assumptions

```
from scipy.stats import ttest_ind

?ttest_ind
```

<https://statistics.laerd.com/statistical-guides/independent-t-test-statistical-guide.php>

- Independence of means

Are the means of our voting data independent (do not affect the outcome of one another)?

The best way to increase thel likelihood of our means being independent is to randomly sample (which we did not do).

- "Homogeneity" of Variance?

Is the magnitude of the variance between the two roughly the same?

I think we're OK on this one for the voting data, although it probably could be better, one party was larger than the other.

If we suspect this to be a problem then we can use Welch's T-test

- "Dependent Variable" (sample means) are Distributed Normally

<https://stats.stackexchange.com/questions/9573/t-test-for-non-normal-when-n50>

Lots of statistical tests depend on normal distributions. We can test for normality using Scipy as was shown above.

This assumption is often assumed even if the assumption is a weak one. If you strongly suspect that things are not normally distributed, you can transform your data to get it looking more normal and then run your test. This problem typically goes away for large sample sizes (yay Central Limit Theorem) and is often why you don't hear it brought up. People declare the assumption to be satisfied either way.

## Central Limit Theorem

```
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

N = 3000
sample_means = []
for x in range(0,N):
  coinflips = np.random.binomial(n=1, p=.5, size=30)
  one_sample = coinflips
  sample_means.append(coinflips.mean())

print(len(sample_means))
print(sample_means)
```

    3000
    [0.5, 0.4, 0.6333333333333333, 0.4666666666666667, 0.6333333333333333, 0.5333333333333333, 0.36666666666666664, 0.4, 0.36666666666666664, 0.3333333333333333, 0.5, 0.4666666666666667, 0.36666666666666664, 0.6, 0.3, 0.43333333333333335, 0.36666666666666664, 0.43333333333333335, 0.5333333333333333, 0.36666666666666664, 0.4666666666666667, 0.6, 0.6, 0.3333333333333333, 0.4666666666666667, 0.36666666666666664, 0.36666666666666664, 0.5333333333333333, 0.4666666666666667, 0.4, 0.6333333333333333, 0.43333333333333335, 0.5666666666666667, 0.5333333333333333, 0.4666666666666667, 0.5, 0.4, 0.4666666666666667, 0.4, 0.4, 0.3, 0.36666666666666664, 0.5666666666666667, 0.4666666666666667, 0.43333333333333335, 0.4, 0.3, 0.5666666666666667, 0.4, 0.4666666666666667, 0.5333333333333333, 0.5, 0.3, 0.5666666666666667, 0.43333333333333335, 0.36666666666666664, 0.5, 0.4666666666666667, 0.4, 0.4666666666666667, 0.5333333333333333, 0.43333333333333335, 0.6333333333333333, 0.4, 0.6333333333333333, 0.4666666666666667, 0.5, 0.6666666666666666, 0.5333333333333333, 0.5333333333333333, 0.5666666666666667, 0.6, 0.36666666666666664, 0.5666666666666667, 0.36666666666666664, 0.5666666666666667, 0.5333333333333333, 0.4666666666666667, 0.5666666666666667, 0.36666666666666664, 0.4, 0.6333333333333333, 0.3333333333333333, 0.6, 0.5666666666666667, 0.43333333333333335, 0.43333333333333335, 0.4666666666666667, 0.4, 0.5333333333333333, 0.43333333333333335, 0.5333333333333333, 0.5666666666666667, 0.5, 0.43333333333333335, 0.36666666666666664, 0.4, 0.5, 0.5, 0.6333333333333333, 0.5, 0.5666666666666667, 0.36666666666666664, 0.5, 0.4666666666666667, 0.43333333333333335, 0.5666666666666667, 0.43333333333333335, 0.5333333333333333, 0.5666666666666667, 0.3, 0.4666666666666667, 0.43333333333333335, 0.43333333333333335, 0.36666666666666664, 0.4, 0.5666666666666667, 0.5666666666666667, 0.5666666666666667, 0.6333333333333333, 0.5, 0.4666666666666667, 0.5333333333333333, 0.5666666666666667, 0.5333333333333333, 0.5, 0.43333333333333335, 0.4666666666666667, 0.36666666666666664, 0.4666666666666667, 0.4, 0.3, 0.6333333333333333, 0.5666666666666667, 0.5, 0.5666666666666667, 0.6, 0.6, 0.5666666666666667, 0.4666666666666667, 0.43333333333333335, 0.6, 0.5, 0.43333333333333335, 0.5666666666666667, 0.5666666666666667, 0.5666666666666667, 0.43333333333333335, 0.6, 0.4666666666666667, 0.4666666666666667, 0.36666666666666664, 0.4666666666666667, 0.5666666666666667, 0.3333333333333333, 0.5333333333333333, 0.4666666666666667, 0.4, 0.43333333333333335, 0.36666666666666664, 0.4666666666666667, 0.5333333333333333, 0.36666666666666664, 0.5, 0.43333333333333335, 0.4, 0.4666666666666667, 0.36666666666666664, 0.36666666666666664, 0.4666666666666667, 0.5666666666666667, 0.36666666666666664, 0.4, 0.4666666666666667, 0.26666666666666666, 0.3333333333333333, 0.5, 0.43333333333333335, 0.6666666666666666, 0.5, 0.4666666666666667, 0.36666666666666664, 0.6, 0.5, 0.43333333333333335, 0.5, 0.4666666666666667, 0.6333333333333333, 0.4666666666666667, 0.3333333333333333, 0.5, 0.5666666666666667, 0.5333333333333333, 0.5, 0.6333333333333333, 0.4666666666666667, 0.26666666666666666, 0.5666666666666667, 0.6, 0.6, 0.5, 0.6333333333333333, 0.5666666666666667, 0.4, 0.5333333333333333, 0.7, 0.6333333333333333, 0.5333333333333333, 0.5333333333333333, 0.5333333333333333, 0.5, 0.43333333333333335, 0.6666666666666666, 0.5333333333333333, 0.26666666666666666, 0.6, 0.4666666666666667, 0.43333333333333335, 0.4666666666666667, 0.3333333333333333, 0.5, 0.43333333333333335, 0.5, 0.3333333333333333, 0.5666666666666667, 0.36666666666666664, 0.36666666666666664, 0.5333333333333333, 0.43333333333333335, 0.4666666666666667, 0.5333333333333333, 0.6666666666666666, 0.5333333333333333, 0.43333333333333335, 0.5333333333333333, 0.6, 0.4, 0.5333333333333333, 0.4666666666666667, 0.5, 0.4666666666666667, 0.5666666666666667, 0.5666666666666667, 0.4666666666666667, 0.5666666666666667, 0.43333333333333335, 0.4666666666666667, 0.5, 0.6, 0.5, 0.5666666666666667, 0.43333333333333335, 0.5333333333333333, 0.5666666666666667, 0.4, 0.43333333333333335, 0.6, 0.5666666666666667, 0.43333333333333335, 0.4666666666666667, 0.5333333333333333, 0.5, 0.3, 0.5, 0.7, 0.36666666666666664, 0.6666666666666666, 0.5333333333333333, 0.7, 0.5666666666666667, 0.5666666666666667, 0.6333333333333333, 0.5666666666666667, 0.4666666666666667, 0.5, 0.43333333333333335, 0.5333333333333333, 0.43333333333333335, 0.5, 0.4666666666666667, 0.5333333333333333, 0.5333333333333333, 0.6666666666666666, 0.5333333333333333, 0.43333333333333335, 0.43333333333333335, 0.4, 0.36666666666666664, 0.5, 0.7, 0.6666666666666666, 0.5, 0.5, 0.5666666666666667, 0.6, 0.36666666666666664, 0.4666666666666667, 0.5, 0.5333333333333333, 0.6, 0.7333333333333333, 0.6, 0.7, 0.4666666666666667, 0.3, 0.5, 0.5333333333333333, 0.4, 0.5, 0.5, 0.5, 0.6, 0.5333333333333333, 0.36666666666666664, 0.4666666666666667, 0.5666666666666667, 0.43333333333333335, 0.5333333333333333, 0.5666666666666667, 0.43333333333333335, 0.6, 0.5, 0.5666666666666667, 0.4666666666666667, 0.36666666666666664, 0.5, 0.5666666666666667, 0.5, 0.5333333333333333, 0.3333333333333333, 0.5333333333333333, 0.5, 0.5666666666666667, 0.4, 0.4666666666666667, 0.4666666666666667, 0.5666666666666667, 0.5333333333333333, 0.6, 0.5666666666666667, 0.5666666666666667, 0.6, 0.5333333333333333, 0.5, 0.6666666666666666, 0.43333333333333335, 0.5, 0.4, 0.43333333333333335, 0.5, 0.4, 0.4666666666666667, 0.4666666666666667, 0.43333333333333335, 0.4, 0.6, 0.4666666666666667, 0.43333333333333335, 0.3333333333333333, 0.6333333333333333, 0.5, 0.5666666666666667, 0.6666666666666666, 0.4666666666666667, 0.5, 0.5333333333333333, 0.26666666666666666, 0.5, 0.5666666666666667, 0.3333333333333333, 0.5666666666666667, 0.5333333333333333, 0.4666666666666667, 0.5333333333333333, 0.5666666666666667, 0.5333333333333333, 0.5, 0.4666666666666667, 0.5, 0.6666666666666666, 0.36666666666666664, 0.6333333333333333, 0.5666666666666667, 0.5333333333333333, 0.5666666666666667, 0.6, 0.6, 0.6333333333333333, 0.4, 0.5, 0.5, 0.6, 0.6333333333333333, 0.4666666666666667, 0.43333333333333335, 0.5, 0.5, 0.4666666666666667, 0.5, 0.4, 0.43333333333333335, 0.4666666666666667, 0.6666666666666666, 0.6666666666666666, 0.43333333333333335, 0.26666666666666666, 0.6, 0.3333333333333333, 0.5666666666666667, 0.4, 0.36666666666666664, 0.16666666666666666, 0.43333333333333335, 0.6333333333333333, 0.6666666666666666, 0.5333333333333333, 0.5666666666666667, 0.6, 0.43333333333333335, 0.4, 0.5666666666666667, 0.5, 0.5666666666666667, 0.5333333333333333, 0.4666666666666667, 0.5666666666666667, 0.7, 0.43333333333333335, 0.5, 0.5, 0.43333333333333335, 0.7, 0.6666666666666666, 0.7333333333333333, 0.43333333333333335, 0.5, 0.6333333333333333, 0.43333333333333335, 0.4, 0.6, 0.43333333333333335, 0.6, 0.4, 0.5666666666666667, 0.7333333333333333, 0.6, 0.3333333333333333, 0.4666666666666667, 0.43333333333333335, 0.6, 0.5333333333333333, 0.6666666666666666, 0.4666666666666667, 0.4666666666666667, 0.5666666666666667, 0.36666666666666664, 0.5333333333333333, 0.4666666666666667, 0.4666666666666667, 0.43333333333333335, 0.5333333333333333, 0.36666666666666664, 0.36666666666666664, 0.4666666666666667, 0.5333333333333333, 0.6, 0.6, 0.43333333333333335, 0.43333333333333335, 0.5, 0.5, 0.5333333333333333, 0.5333333333333333, 0.6333333333333333, 0.5666666666666667, 0.5333333333333333, 0.43333333333333335, 0.4666666666666667, 0.6333333333333333, 0.5, 0.6, 0.6, 0.4666666666666667, 0.4, 0.5666666666666667, 0.5, 0.5, 0.6333333333333333, 0.4666666666666667, 0.5666666666666667, 0.4, 0.43333333333333335, 0.3333333333333333, 0.43333333333333335, 0.36666666666666664, 0.4666666666666667, 0.6, 0.6333333333333333, 0.6, 0.5666666666666667, 0.26666666666666666, 0.5, 0.5, 0.6, 0.6333333333333333, 0.5, 0.4, 0.6, 0.6, 0.6333333333333333, 0.4, 0.43333333333333335, 0.5333333333333333, 0.3333333333333333, 0.5666666666666667, 0.6, 0.6, 0.5333333333333333, 0.43333333333333335, 0.4666666666666667, 0.43333333333333335, 0.4666666666666667, 0.5, 0.6666666666666666, 0.3333333333333333, 0.4, 0.36666666666666664, 0.6, 0.5666666666666667, 0.5, 0.5666666666666667, 0.5666666666666667, 0.4, 0.6333333333333333, 0.4666666666666667, 0.4666666666666667, 0.5666666666666667, 0.5333333333333333, 0.4666666666666667, 0.3333333333333333, 0.6333333333333333, 0.7, 0.4, 0.43333333333333335, 0.5333333333333333, 0.6333333333333333, 0.36666666666666664, 0.4666666666666667, 0.6666666666666666, 0.4666666666666667, 0.3333333333333333, 0.4, 0.3333333333333333, 0.4666666666666667, 0.3333333333333333, 0.5, 0.5666666666666667, 0.5, 0.5, 0.4, 0.4, 0.5, 0.4666666666666667, 0.4, 0.43333333333333335, 0.6666666666666666, 0.6, 0.26666666666666666, 0.5666666666666667, 0.7, 0.26666666666666666, 0.4, 0.5, 0.5666666666666667, 0.4666666666666667, 0.5666666666666667, 0.4666666666666667, 0.5666666666666667, 0.5, 0.36666666666666664, 0.6333333333333333, 0.5333333333333333, 0.4, 0.43333333333333335, 0.4666666666666667, 0.5, 0.5666666666666667, 0.4, 0.43333333333333335, 0.4666666666666667, 0.43333333333333335, 0.4, 0.5, 0.3, 0.6, 0.6333333333333333, 0.6, 0.4666666666666667, 0.6, 0.43333333333333335, 0.5666666666666667, 0.43333333333333335, 0.43333333333333335, 0.5666666666666667, 0.4666666666666667, 0.5666666666666667, 0.5, 0.5333333333333333, 0.5, 0.5333333333333333, 0.5666666666666667, 0.36666666666666664, 0.4, 0.4666666666666667, 0.5666666666666667, 0.6, 0.6, 0.5, 0.3333333333333333, 0.43333333333333335, 0.6, 0.5333333333333333, 0.36666666666666664, 0.5666666666666667, 0.5, 0.43333333333333335, 0.6333333333333333, 0.43333333333333335, 0.5666666666666667, 0.6, 0.4666666666666667, 0.5333333333333333, 0.6, 0.4, 0.3333333333333333, 0.6, 0.5, 0.36666666666666664, 0.5, 0.43333333333333335, 0.7333333333333333, 0.4, 0.43333333333333335, 0.4666666666666667, 0.5666666666666667, 0.5333333333333333, 0.5666666666666667, 0.6666666666666666, 0.4666666666666667, 0.4666666666666667, 0.5666666666666667, 0.43333333333333335, 0.4666666666666667, 0.5333333333333333, 0.4666666666666667, 0.36666666666666664, 0.5, 0.3, 0.43333333333333335, 0.36666666666666664, 0.5666666666666667, 0.26666666666666666, 0.5333333333333333, 0.5, 0.6, 0.4666666666666667, 0.3333333333333333, 0.6333333333333333, 0.6333333333333333, 0.5333333333333333, 0.6, 0.4666666666666667, 0.5333333333333333, 0.5333333333333333, 0.5333333333333333, 0.6, 0.43333333333333335, 0.5333333333333333, 0.5, 0.6, 0.5666666666666667, 0.3333333333333333, 0.4, 0.4666666666666667, 0.5666666666666667, 0.4666666666666667, 0.5, 0.5333333333333333, 0.6333333333333333, 0.4666666666666667, 0.36666666666666664, 0.43333333333333335, 0.5333333333333333, 0.5, 0.43333333333333335, 0.5666666666666667, 0.5, 0.5, 0.7, 0.6333333333333333, 0.43333333333333335, 0.5666666666666667, 0.4666666666666667, 0.5666666666666667, 0.4666666666666667, 0.36666666666666664, 0.5, 0.4666666666666667, 0.4666666666666667, 0.4666666666666667, 0.36666666666666664, 0.4, 0.4666666666666667, 0.5, 0.4666666666666667, 0.43333333333333335, 0.4, 0.5, 0.43333333333333335, 0.5, 0.5666666666666667, 0.36666666666666664, 0.43333333333333335, 0.43333333333333335, 0.5666666666666667, 0.36666666666666664, 0.5333333333333333, 0.5, 0.43333333333333335, 0.43333333333333335, 0.36666666666666664, 0.3333333333333333, 0.43333333333333335, 0.6333333333333333, 0.6333333333333333, 0.5, 0.4666666666666667, 0.5, 0.5666666666666667, 0.5, 0.5333333333333333, 0.6, 0.43333333333333335, 0.4666666666666667, 0.5333333333333333, 0.5, 0.4666666666666667, 0.7, 0.6666666666666666, 0.43333333333333335, 0.43333333333333335, 0.5666666666666667, 0.43333333333333335, 0.4666666666666667, 0.6333333333333333, 0.4666666666666667, 0.7, 0.5, 0.4, 0.43333333333333335, 0.4, 0.36666666666666664, 0.5666666666666667, 0.43333333333333335, 0.4666666666666667, 0.5666666666666667, 0.6, 0.4666666666666667, 0.4666666666666667, 0.5, 0.5, 0.4666666666666667, 0.4666666666666667, 0.5333333333333333, 0.5, 0.4666666666666667, 0.4, 0.5666666666666667, 0.6333333333333333, 0.43333333333333335, 0.36666666666666664, 0.4666666666666667, 0.4666666666666667, 0.6, 0.5, 0.4, 0.5, 0.5333333333333333, 0.5333333333333333, 0.5, 0.43333333333333335, 0.43333333333333335, 0.5333333333333333, 0.43333333333333335, 0.4, 0.5, 0.43333333333333335, 0.6333333333333333, 0.5, 0.5, 0.3, 0.5666666666666667, 0.6666666666666666, 0.4666666666666667, 0.5333333333333333, 0.5, 0.4666666666666667, 0.6, 0.6666666666666666, 0.5, 0.4666666666666667, 0.5, 0.4666666666666667, 0.6333333333333333, 0.5, 0.7666666666666667, 0.5333333333333333, 0.5, 0.5, 0.5333333333333333, 0.43333333333333335, 0.5, 0.4666666666666667, 0.6, 0.6, 0.5, 0.36666666666666664, 0.4, 0.4666666666666667, 0.36666666666666664, 0.5666666666666667, 0.5666666666666667, 0.5666666666666667, 0.3333333333333333, 0.5333333333333333, 0.7333333333333333, 0.6, 0.3, 0.6333333333333333, 0.5666666666666667, 0.43333333333333335, 0.4666666666666667, 0.6333333333333333, 0.4, 0.4, 0.7333333333333333, 0.5333333333333333, 0.6333333333333333, 0.5, 0.36666666666666664, 0.4666666666666667, 0.5666666666666667, 0.43333333333333335, 0.5666666666666667, 0.6333333333333333, 0.4666666666666667, 0.6, 0.4666666666666667, 0.43333333333333335, 0.4666666666666667, 0.5, 0.5333333333333333, 0.5, 0.6, 0.5, 0.4666666666666667, 0.4, 0.43333333333333335, 0.43333333333333335, 0.36666666666666664, 0.4666666666666667, 0.4666666666666667, 0.5666666666666667, 0.43333333333333335, 0.5333333333333333, 0.6, 0.4666666666666667, 0.6, 0.43333333333333335, 0.43333333333333335, 0.43333333333333335, 0.43333333333333335, 0.5666666666666667, 0.5, 0.5333333333333333, 0.5333333333333333, 0.6666666666666666, 0.4, 0.5, 0.6, 0.36666666666666664, 0.4666666666666667, 0.3333333333333333, 0.6, 0.5666666666666667, 0.5, 0.3, 0.4, 0.4666666666666667, 0.36666666666666664, 0.6333333333333333, 0.5666666666666667, 0.4, 0.6, 0.6333333333333333, 0.4666666666666667, 0.5666666666666667, 0.5, 0.3333333333333333, 0.5333333333333333, 0.5666666666666667, 0.5333333333333333, 0.6, 0.4, 0.43333333333333335, 0.5333333333333333, 0.6333333333333333, 0.4, 0.5, 0.5, 0.6, 0.43333333333333335, 0.5333333333333333, 0.43333333333333335, 0.5, 0.5666666666666667, 0.5333333333333333, 0.5333333333333333, 0.5333333333333333, 0.5666666666666667, 0.43333333333333335, 0.4, 0.5333333333333333, 0.5666666666666667, 0.43333333333333335, 0.43333333333333335, 0.5666666666666667, 0.5, 0.6, 0.36666666666666664, 0.4, 0.5666666666666667, 0.6333333333333333, 0.23333333333333334, 0.4666666666666667, 0.4666666666666667, 0.5333333333333333, 0.4, 0.4666666666666667, 0.6333333333333333, 0.5333333333333333, 0.36666666666666664, 0.6, 0.7333333333333333, 0.3, 0.3, 0.5333333333333333, 0.43333333333333335, 0.4, 0.3333333333333333, 0.5, 0.6, 0.5333333333333333, 0.4666666666666667, 0.5666666666666667, 0.5333333333333333, 0.6, 0.5, 0.43333333333333335, 0.3, 0.6333333333333333, 0.5666666666666667, 0.5, 0.5333333333333333, 0.5666666666666667, 0.6666666666666666, 0.4666666666666667, 0.43333333333333335, 0.6, 0.3333333333333333, 0.43333333333333335, 0.4666666666666667, 0.4666666666666667, 0.4666666666666667, 0.4666666666666667, 0.5, 0.4, 0.4, 0.3333333333333333, 0.5666666666666667, 0.36666666666666664, 0.5, 0.3333333333333333, 0.36666666666666664, 0.43333333333333335, 0.4, 0.4666666666666667, 0.4666666666666667, 0.4, 0.6, 0.43333333333333335, 0.36666666666666664, 0.4666666666666667, 0.5, 0.5333333333333333, 0.43333333333333335, 0.6, 0.5333333333333333, 0.4666666666666667, 0.6, 0.5333333333333333, 0.6333333333333333, 0.4666666666666667, 0.4666666666666667, 0.5666666666666667, 0.4666666666666667, 0.5666666666666667, 0.6, 0.5, 0.5666666666666667, 0.5333333333333333, 0.5333333333333333, 0.4666666666666667, 0.5666666666666667, 0.6333333333333333, 0.43333333333333335, 0.43333333333333335, 0.3333333333333333, 0.4, 0.5333333333333333, 0.4666666666666667, 0.43333333333333335, 0.5, 0.7333333333333333, 0.36666666666666664, 0.6, 0.5333333333333333, 0.5333333333333333, 0.5333333333333333, 0.43333333333333335, 0.5, 0.43333333333333335, 0.5666666666666667, 0.5333333333333333, 0.5666666666666667, 0.4666666666666667, 0.5333333333333333, 0.4666666666666667, 0.6333333333333333, 0.5, 0.5, 0.36666666666666664, 0.43333333333333335, 0.5, 0.5, 0.36666666666666664, 0.5666666666666667, 0.7, 0.7, 0.6, 0.4, 0.5, 0.6333333333333333, 0.26666666666666666, 0.26666666666666666, 0.5666666666666667, 0.36666666666666664, 0.6666666666666666, 0.5666666666666667, 0.6, 0.6333333333333333, 0.6333333333333333, 0.6333333333333333, 0.4, 0.5, 0.43333333333333335, 0.4, 0.43333333333333335, 0.5333333333333333, 0.43333333333333335, 0.43333333333333335, 0.4666666666666667, 0.4, 0.4666666666666667, 0.5, 0.5, 0.7, 0.4, 0.5333333333333333, 0.6, 0.23333333333333334, 0.43333333333333335, 0.5, 0.5, 0.43333333333333335, 0.5, 0.5, 0.5, 0.36666666666666664, 0.5666666666666667, 0.4, 0.36666666666666664, 0.4, 0.5666666666666667, 0.43333333333333335, 0.6333333333333333, 0.4666666666666667, 0.5666666666666667, 0.7, 0.5, 0.5333333333333333, 0.6, 0.5, 0.5333333333333333, 0.4666666666666667, 0.4666666666666667, 0.5666666666666667, 0.36666666666666664, 0.5333333333333333, 0.6, 0.5333333333333333, 0.6333333333333333, 0.4666666666666667, 0.5666666666666667, 0.6333333333333333, 0.6, 0.6666666666666666, 0.5666666666666667, 0.6666666666666666, 0.4666666666666667, 0.4666666666666667, 0.5666666666666667, 0.36666666666666664, 0.5, 0.5, 0.5, 0.4666666666666667, 0.6, 0.5, 0.5666666666666667, 0.5333333333333333, 0.7, 0.5, 0.5, 0.4, 0.5, 0.5666666666666667, 0.43333333333333335, 0.7, 0.6, 0.5333333333333333, 0.4, 0.6333333333333333, 0.5333333333333333, 0.5333333333333333, 0.3333333333333333, 0.2, 0.43333333333333335, 0.5, 0.5666666666666667, 0.43333333333333335, 0.5, 0.4666666666666667, 0.5333333333333333, 0.4666666666666667, 0.6, 0.4, 0.4666666666666667, 0.4666666666666667, 0.3, 0.5, 0.6333333333333333, 0.5333333333333333, 0.4666666666666667, 0.6, 0.7, 0.5333333333333333, 0.5, 0.4666666666666667, 0.5666666666666667, 0.6, 0.43333333333333335, 0.4666666666666667, 0.4666666666666667, 0.36666666666666664, 0.5, 0.4, 0.5, 0.5, 0.5333333333333333, 0.43333333333333335, 0.4666666666666667, 0.5666666666666667, 0.43333333333333335, 0.4666666666666667, 0.5, 0.4666666666666667, 0.5, 0.4666666666666667, 0.36666666666666664, 0.7, 0.6, 0.43333333333333335, 0.4, 0.5, 0.5, 0.5333333333333333, 0.5, 0.5, 0.5, 0.4, 0.5, 0.5666666666666667, 0.3, 0.4, 0.5333333333333333, 0.5, 0.6666666666666666, 0.5, 0.3333333333333333, 0.43333333333333335, 0.4666666666666667, 0.36666666666666664, 0.6, 0.5333333333333333, 0.43333333333333335, 0.3333333333333333, 0.4, 0.5, 0.43333333333333335, 0.5, 0.5, 0.36666666666666664, 0.5, 0.43333333333333335, 0.5, 0.5333333333333333, 0.36666666666666664, 0.6333333333333333, 0.6333333333333333, 0.4666666666666667, 0.5, 0.4666666666666667, 0.5666666666666667, 0.3333333333333333, 0.5333333333333333, 0.36666666666666664, 0.4666666666666667, 0.4666666666666667, 0.5333333333333333, 0.5333333333333333, 0.5666666666666667, 0.6, 0.5333333333333333, 0.4666666666666667, 0.6, 0.5666666666666667, 0.5666666666666667, 0.36666666666666664, 0.5, 0.43333333333333335, 0.6666666666666666, 0.43333333333333335, 0.36666666666666664, 0.5333333333333333, 0.5666666666666667, 0.6333333333333333, 0.4, 0.36666666666666664, 0.5333333333333333, 0.6666666666666666, 0.6666666666666666, 0.6666666666666666, 0.5, 0.5333333333333333, 0.5333333333333333, 0.36666666666666664, 0.4, 0.4, 0.5333333333333333, 0.5666666666666667, 0.6333333333333333, 0.5, 0.43333333333333335, 0.5333333333333333, 0.5666666666666667, 0.5333333333333333, 0.3, 0.6, 0.43333333333333335, 0.43333333333333335, 0.4, 0.4666666666666667, 0.4666666666666667, 0.5, 0.5, 0.5, 0.6333333333333333, 0.6, 0.6666666666666666, 0.5666666666666667, 0.43333333333333335, 0.36666666666666664, 0.5333333333333333, 0.43333333333333335, 0.8, 0.5, 0.43333333333333335, 0.4666666666666667, 0.5666666666666667, 0.5, 0.36666666666666664, 0.5, 0.6, 0.5333333333333333, 0.4, 0.4666666666666667, 0.5666666666666667, 0.6333333333333333, 0.36666666666666664, 0.5, 0.5666666666666667, 0.5, 0.5666666666666667, 0.43333333333333335, 0.5666666666666667, 0.4, 0.36666666666666664, 0.4, 0.43333333333333335, 0.4, 0.5333333333333333, 0.43333333333333335, 0.43333333333333335, 0.36666666666666664, 0.5333333333333333, 0.5, 0.5, 0.43333333333333335, 0.5666666666666667, 0.5666666666666667, 0.5333333333333333, 0.43333333333333335, 0.43333333333333335, 0.36666666666666664, 0.4, 0.43333333333333335, 0.6666666666666666, 0.4, 0.5666666666666667, 0.5333333333333333, 0.36666666666666664, 0.43333333333333335, 0.4, 0.5333333333333333, 0.5, 0.6666666666666666, 0.6333333333333333, 0.4666666666666667, 0.5333333333333333, 0.5666666666666667, 0.4, 0.43333333333333335, 0.6, 0.7, 0.43333333333333335, 0.43333333333333335, 0.5666666666666667, 0.5, 0.36666666666666664, 0.4666666666666667, 0.36666666666666664, 0.6, 0.43333333333333335, 0.5, 0.4666666666666667, 0.5666666666666667, 0.6, 0.4666666666666667, 0.5, 0.7, 0.5333333333333333, 0.43333333333333335, 0.5333333333333333, 0.5, 0.4666666666666667, 0.6, 0.4666666666666667, 0.5, 0.5333333333333333, 0.4666666666666667, 0.5, 0.43333333333333335, 0.4666666666666667, 0.4, 0.36666666666666664, 0.5, 0.7, 0.4, 0.5333333333333333, 0.4, 0.6666666666666666, 0.4666666666666667, 0.43333333333333335, 0.5333333333333333, 0.5666666666666667, 0.43333333333333335, 0.43333333333333335, 0.5, 0.6333333333333333, 0.5666666666666667, 0.4666666666666667, 0.5, 0.4666666666666667, 0.4, 0.6, 0.4, 0.5666666666666667, 0.5666666666666667, 0.6, 0.43333333333333335, 0.6666666666666666, 0.5666666666666667, 0.43333333333333335, 0.4666666666666667, 0.4, 0.5, 0.43333333333333335, 0.4, 0.43333333333333335, 0.5, 0.4, 0.7, 0.3333333333333333, 0.36666666666666664, 0.6, 0.5333333333333333, 0.43333333333333335, 0.4666666666666667, 0.6333333333333333, 0.5, 0.4, 0.5666666666666667, 0.43333333333333335, 0.36666666666666664, 0.5333333333333333, 0.5666666666666667, 0.5666666666666667, 0.6, 0.4, 0.6, 0.6666666666666666, 0.6, 0.5, 0.43333333333333335, 0.4, 0.36666666666666664, 0.43333333333333335, 0.4, 0.4666666666666667, 0.4666666666666667, 0.5666666666666667, 0.4, 0.4, 0.6, 0.43333333333333335, 0.5333333333333333, 0.5333333333333333, 0.36666666666666664, 0.4, 0.5333333333333333, 0.5, 0.36666666666666664, 0.4666666666666667, 0.36666666666666664, 0.7, 0.43333333333333335, 0.5666666666666667, 0.5, 0.3333333333333333, 0.6666666666666666, 0.6, 0.5333333333333333, 0.4, 0.43333333333333335, 0.5, 0.4666666666666667, 0.6666666666666666, 0.36666666666666664, 0.4, 0.26666666666666666, 0.43333333333333335, 0.4666666666666667, 0.5, 0.43333333333333335, 0.5, 0.6, 0.4, 0.5, 0.6, 0.6666666666666666, 0.43333333333333335, 0.4666666666666667, 0.5333333333333333, 0.5, 0.43333333333333335, 0.5333333333333333, 0.5666666666666667, 0.5666666666666667, 0.36666666666666664, 0.5, 0.6333333333333333, 0.5666666666666667, 0.3333333333333333, 0.5, 0.4666666666666667, 0.5, 0.6333333333333333, 0.6333333333333333, 0.36666666666666664, 0.5333333333333333, 0.4666666666666667, 0.36666666666666664, 0.5333333333333333, 0.36666666666666664, 0.4, 0.5666666666666667, 0.36666666666666664, 0.5, 0.6666666666666666, 0.5333333333333333, 0.6, 0.43333333333333335, 0.43333333333333335, 0.43333333333333335, 0.5666666666666667, 0.4, 0.5666666666666667, 0.43333333333333335, 0.4666666666666667, 0.43333333333333335, 0.5333333333333333, 0.4666666666666667, 0.6333333333333333, 0.6, 0.4666666666666667, 0.5, 0.7, 0.43333333333333335, 0.5333333333333333, 0.5333333333333333, 0.4, 0.6333333333333333, 0.5666666666666667, 0.6, 0.4666666666666667, 0.36666666666666664, 0.5, 0.5333333333333333, 0.4, 0.4666666666666667, 0.5, 0.43333333333333335, 0.4666666666666667, 0.4666666666666667, 0.4666666666666667, 0.5666666666666667, 0.4666666666666667, 0.43333333333333335, 0.4666666666666667, 0.6666666666666666, 0.3, 0.36666666666666664, 0.5666666666666667, 0.36666666666666664, 0.4666666666666667, 0.4666666666666667, 0.5, 0.5666666666666667, 0.4666666666666667, 0.4, 0.7, 0.4, 0.4, 0.4666666666666667, 0.36666666666666664, 0.5, 0.4, 0.6, 0.6, 0.3333333333333333, 0.43333333333333335, 0.5333333333333333, 0.43333333333333335, 0.4666666666666667, 0.6333333333333333, 0.43333333333333335, 0.5, 0.4666666666666667, 0.5, 0.4666666666666667, 0.5, 0.4666666666666667, 0.4666666666666667, 0.3, 0.5, 0.5333333333333333, 0.5333333333333333, 0.4, 0.6, 0.7333333333333333, 0.4666666666666667, 0.5666666666666667, 0.5, 0.5333333333333333, 0.36666666666666664, 0.3333333333333333, 0.5333333333333333, 0.5, 0.5, 0.5333333333333333, 0.7333333333333333, 0.5, 0.5, 0.6, 0.5666666666666667, 0.6, 0.3333333333333333, 0.4666666666666667, 0.5, 0.5333333333333333, 0.5, 0.43333333333333335, 0.36666666666666664, 0.4666666666666667, 0.5, 0.5333333333333333, 0.4, 0.5333333333333333, 0.5, 0.43333333333333335, 0.5666666666666667, 0.5, 0.4666666666666667, 0.4666666666666667, 0.5333333333333333, 0.4666666666666667, 0.6333333333333333, 0.5333333333333333, 0.6, 0.6, 0.5, 0.43333333333333335, 0.5, 0.6333333333333333, 0.36666666666666664, 0.3, 0.4, 0.5666666666666667, 0.5333333333333333, 0.6666666666666666, 0.5666666666666667, 0.43333333333333335, 0.3, 0.5333333333333333, 0.4, 0.5333333333333333, 0.43333333333333335, 0.7, 0.43333333333333335, 0.5666666666666667, 0.5333333333333333, 0.5, 0.5, 0.4666666666666667, 0.4, 0.4666666666666667, 0.3333333333333333, 0.6, 0.6333333333333333, 0.4, 0.5666666666666667, 0.6666666666666666, 0.3, 0.4, 0.43333333333333335, 0.43333333333333335, 0.5, 0.5, 0.43333333333333335, 0.5666666666666667, 0.43333333333333335, 0.43333333333333335, 0.3333333333333333, 0.43333333333333335, 0.4666666666666667, 0.43333333333333335, 0.43333333333333335, 0.5666666666666667, 0.5333333333333333, 0.5, 0.5333333333333333, 0.5333333333333333, 0.4666666666666667, 0.4666666666666667, 0.4, 0.4666666666666667, 0.6, 0.6333333333333333, 0.5666666666666667, 0.5333333333333333, 0.6333333333333333, 0.5666666666666667, 0.36666666666666664, 0.5666666666666667, 0.4666666666666667, 0.4666666666666667, 0.5333333333333333, 0.4666666666666667, 0.6, 0.36666666666666664, 0.4, 0.6, 0.5, 0.5333333333333333, 0.5, 0.5333333333333333, 0.5666666666666667, 0.5, 0.3333333333333333, 0.5, 0.4, 0.6, 0.5666666666666667, 0.5666666666666667, 0.5666666666666667, 0.5333333333333333, 0.6666666666666666, 0.6666666666666666, 0.5666666666666667, 0.43333333333333335, 0.43333333333333335, 0.43333333333333335, 0.6, 0.5333333333333333, 0.5666666666666667, 0.5, 0.6333333333333333, 0.4, 0.4, 0.6, 0.5666666666666667, 0.5, 0.4666666666666667, 0.4666666666666667, 0.36666666666666664, 0.5, 0.43333333333333335, 0.5666666666666667, 0.43333333333333335, 0.4666666666666667, 0.6666666666666666, 0.5, 0.6333333333333333, 0.5333333333333333, 0.5666666666666667, 0.5333333333333333, 0.6666666666666666, 0.4, 0.7, 0.4666666666666667, 0.5, 0.5, 0.4, 0.5, 0.4666666666666667, 0.5333333333333333, 0.7333333333333333, 0.5333333333333333, 0.5333333333333333, 0.5333333333333333, 0.43333333333333335, 0.4666666666666667, 0.3, 0.4666666666666667, 0.4666666666666667, 0.4, 0.4666666666666667, 0.6, 0.4, 0.5333333333333333, 0.6333333333333333, 0.4666666666666667, 0.6333333333333333, 0.4666666666666667, 0.6, 0.5666666666666667, 0.5, 0.5333333333333333, 0.4666666666666667, 0.5333333333333333, 0.4666666666666667, 0.6333333333333333, 0.5333333333333333, 0.5333333333333333, 0.5, 0.36666666666666664, 0.6333333333333333, 0.5, 0.6666666666666666, 0.43333333333333335, 0.4666666666666667, 0.6333333333333333, 0.5, 0.3333333333333333, 0.3333333333333333, 0.36666666666666664, 0.5666666666666667, 0.5, 0.36666666666666664, 0.6333333333333333, 0.5333333333333333, 0.6333333333333333, 0.6, 0.5666666666666667, 0.5, 0.4666666666666667, 0.4666666666666667, 0.6, 0.5, 0.43333333333333335, 0.4666666666666667, 0.6, 0.4666666666666667, 0.4, 0.43333333333333335, 0.5, 0.4, 0.4, 0.36666666666666664, 0.4666666666666667, 0.6666666666666666, 0.43333333333333335, 0.3333333333333333, 0.6333333333333333, 0.6, 0.36666666666666664, 0.43333333333333335, 0.5333333333333333, 0.5, 0.5333333333333333, 0.4, 0.6, 0.5333333333333333, 0.43333333333333335, 0.5666666666666667, 0.6666666666666666, 0.43333333333333335, 0.36666666666666664, 0.5666666666666667, 0.4666666666666667, 0.6333333333333333, 0.43333333333333335, 0.4666666666666667, 0.4666666666666667, 0.5333333333333333, 0.5, 0.3333333333333333, 0.6666666666666666, 0.5333333333333333, 0.36666666666666664, 0.36666666666666664, 0.4666666666666667, 0.43333333333333335, 0.4666666666666667, 0.5666666666666667, 0.43333333333333335, 0.43333333333333335, 0.5, 0.5333333333333333, 0.5, 0.36666666666666664, 0.4, 0.5333333333333333, 0.4, 0.3333333333333333, 0.5666666666666667, 0.6333333333333333, 0.43333333333333335, 0.5, 0.6, 0.5333333333333333, 0.3333333333333333, 0.4666666666666667, 0.5333333333333333, 0.5333333333333333, 0.4666666666666667, 0.43333333333333335, 0.43333333333333335, 0.6666666666666666, 0.5666666666666667, 0.5, 0.5, 0.6333333333333333, 0.5666666666666667, 0.43333333333333335, 0.4666666666666667, 0.5666666666666667, 0.43333333333333335, 0.5, 0.4, 0.4, 0.5333333333333333, 0.6333333333333333, 0.7, 0.5666666666666667, 0.4666666666666667, 0.43333333333333335, 0.43333333333333335, 0.4666666666666667, 0.5, 0.5, 0.5666666666666667, 0.4666666666666667, 0.4666666666666667, 0.43333333333333335, 0.4666666666666667, 0.43333333333333335, 0.5666666666666667, 0.6, 0.43333333333333335, 0.3333333333333333, 0.5, 0.4666666666666667, 0.5666666666666667, 0.43333333333333335, 0.6, 0.4666666666666667, 0.5666666666666667, 0.5333333333333333, 0.4666666666666667, 0.7, 0.5333333333333333, 0.3333333333333333, 0.6666666666666666, 0.6333333333333333, 0.5666666666666667, 0.4666666666666667, 0.4666666666666667, 0.5333333333333333, 0.6, 0.4, 0.36666666666666664, 0.5666666666666667, 0.3, 0.3333333333333333, 0.4, 0.36666666666666664, 0.4666666666666667, 0.5, 0.5, 0.5333333333333333, 0.36666666666666664, 0.5333333333333333, 0.5, 0.6, 0.4666666666666667, 0.6333333333333333, 0.6333333333333333, 0.3333333333333333, 0.4666666666666667, 0.5333333333333333, 0.4666666666666667, 0.5666666666666667, 0.43333333333333335, 0.36666666666666664, 0.43333333333333335, 0.4666666666666667, 0.6666666666666666, 0.6, 0.3333333333333333, 0.7, 0.5333333333333333, 0.5, 0.4, 0.4, 0.36666666666666664, 0.4666666666666667, 0.6666666666666666, 0.6, 0.5, 0.5333333333333333, 0.4666666666666667, 0.5666666666666667, 0.4, 0.4666666666666667, 0.43333333333333335, 0.5, 0.5, 0.3333333333333333, 0.5, 0.6, 0.5666666666666667, 0.5, 0.6333333333333333, 0.43333333333333335, 0.5, 0.43333333333333335, 0.3, 0.5333333333333333, 0.5333333333333333, 0.4666666666666667, 0.5666666666666667, 0.5666666666666667, 0.5333333333333333, 0.3333333333333333, 0.3, 0.6, 0.5666666666666667, 0.5666666666666667, 0.6333333333333333, 0.43333333333333335, 0.5666666666666667, 0.5, 0.36666666666666664, 0.5333333333333333, 0.5333333333333333, 0.4, 0.5, 0.5666666666666667, 0.5666666666666667, 0.43333333333333335, 0.5, 0.43333333333333335, 0.6333333333333333, 0.5, 0.5333333333333333, 0.4, 0.6, 0.4, 0.4666666666666667, 0.5333333333333333, 0.4666666666666667, 0.4666666666666667, 0.5, 0.5, 0.6, 0.5666666666666667, 0.4666666666666667, 0.43333333333333335, 0.5, 0.36666666666666664, 0.5, 0.4, 0.4, 0.5, 0.4666666666666667, 0.4, 0.43333333333333335, 0.4, 0.36666666666666664, 0.4666666666666667, 0.6666666666666666, 0.5, 0.3, 0.36666666666666664, 0.5, 0.36666666666666664, 0.5333333333333333, 0.4, 0.6333333333333333, 0.5666666666666667, 0.3, 0.5, 0.4, 0.5, 0.3, 0.6, 0.5666666666666667, 0.4666666666666667, 0.5, 0.5666666666666667, 0.4, 0.6, 0.4, 0.5333333333333333, 0.4666666666666667, 0.5666666666666667, 0.5, 0.4666666666666667, 0.4666666666666667, 0.6, 0.4666666666666667, 0.3333333333333333, 0.36666666666666664, 0.5333333333333333, 0.36666666666666664, 0.23333333333333334, 0.4666666666666667, 0.4666666666666667, 0.6, 0.4666666666666667, 0.5, 0.5666666666666667, 0.4666666666666667, 0.5666666666666667, 0.6666666666666666, 0.4, 0.7, 0.6666666666666666, 0.36666666666666664, 0.36666666666666664, 0.5, 0.5, 0.5, 0.43333333333333335, 0.5, 0.4666666666666667, 0.5666666666666667, 0.4666666666666667, 0.6666666666666666, 0.36666666666666664, 0.5, 0.6333333333333333, 0.5, 0.6333333333333333, 0.6, 0.5333333333333333, 0.4666666666666667, 0.6, 0.6, 0.4, 0.4, 0.4, 0.5, 0.36666666666666664, 0.5333333333333333, 0.5, 0.4, 0.36666666666666664, 0.5666666666666667, 0.6, 0.6, 0.6, 0.4, 0.26666666666666666, 0.3333333333333333, 0.5, 0.5333333333333333, 0.6, 0.5666666666666667, 0.4, 0.6, 0.6, 0.6666666666666666, 0.5, 0.43333333333333335, 0.3, 0.4666666666666667, 0.5666666666666667, 0.6333333333333333, 0.4, 0.43333333333333335, 0.5, 0.4666666666666667, 0.36666666666666664, 0.43333333333333335, 0.5, 0.5, 0.4666666666666667, 0.6, 0.6333333333333333, 0.43333333333333335, 0.4, 0.5666666666666667, 0.43333333333333335, 0.4, 0.4666666666666667, 0.4666666666666667, 0.4, 0.6, 0.6, 0.4, 0.5333333333333333, 0.43333333333333335, 0.5333333333333333, 0.5, 0.5666666666666667, 0.5666666666666667, 0.5, 0.6, 0.43333333333333335, 0.26666666666666666, 0.5666666666666667, 0.5666666666666667, 0.43333333333333335, 0.4666666666666667, 0.5333333333333333, 0.5333333333333333, 0.5666666666666667, 0.5666666666666667, 0.6333333333333333, 0.5666666666666667, 0.5333333333333333, 0.5, 0.5666666666666667, 0.5666666666666667, 0.4666666666666667, 0.5666666666666667, 0.5, 0.43333333333333335, 0.5333333333333333, 0.5666666666666667, 0.5666666666666667, 0.6333333333333333, 0.4, 0.4666666666666667, 0.5333333333333333, 0.4666666666666667, 0.43333333333333335, 0.5, 0.5, 0.5333333333333333, 0.5666666666666667, 0.5666666666666667, 0.5333333333333333, 0.8, 0.4666666666666667, 0.43333333333333335, 0.4666666666666667, 0.43333333333333335, 0.4666666666666667, 0.36666666666666664, 0.5, 0.5, 0.4666666666666667, 0.6, 0.5666666666666667, 0.5, 0.4, 0.43333333333333335, 0.4, 0.5, 0.36666666666666664, 0.4666666666666667, 0.5, 0.4, 0.5333333333333333, 0.4, 0.6, 0.43333333333333335, 0.36666666666666664, 0.5666666666666667, 0.6, 0.26666666666666666, 0.4666666666666667, 0.5, 0.5333333333333333, 0.5, 0.4666666666666667, 0.5333333333333333, 0.6, 0.43333333333333335, 0.6333333333333333, 0.5333333333333333, 0.4666666666666667, 0.5666666666666667, 0.4666666666666667, 0.5666666666666667, 0.26666666666666666, 0.3, 0.4666666666666667, 0.5333333333333333, 0.5, 0.4666666666666667, 0.5666666666666667, 0.5666666666666667, 0.4666666666666667, 0.5, 0.4, 0.4666666666666667, 0.5, 0.6, 0.3, 0.5333333333333333, 0.5333333333333333, 0.43333333333333335, 0.4, 0.4, 0.43333333333333335, 0.4666666666666667, 0.43333333333333335, 0.5333333333333333, 0.4666666666666667, 0.43333333333333335, 0.43333333333333335, 0.5666666666666667, 0.5, 0.4666666666666667, 0.7, 0.5666666666666667, 0.5, 0.5, 0.5666666666666667, 0.36666666666666664, 0.4666666666666667, 0.26666666666666666, 0.3333333333333333, 0.3, 0.43333333333333335, 0.5, 0.5666666666666667, 0.5666666666666667, 0.3333333333333333, 0.4, 0.5666666666666667, 0.4666666666666667, 0.6666666666666666, 0.4666666666666667, 0.5666666666666667, 0.6, 0.5333333333333333, 0.6, 0.5, 0.5333333333333333, 0.6333333333333333, 0.5666666666666667, 0.43333333333333335, 0.36666666666666664, 0.5, 0.4, 0.4666666666666667, 0.4666666666666667, 0.6, 0.6, 0.43333333333333335, 0.36666666666666664, 0.6333333333333333, 0.4, 0.5, 0.4666666666666667, 0.6333333333333333, 0.6333333333333333, 0.5, 0.5, 0.43333333333333335, 0.3333333333333333, 0.7666666666666667, 0.6, 0.5666666666666667, 0.5333333333333333, 0.7333333333333333, 0.3333333333333333, 0.5, 0.5666666666666667, 0.5333333333333333, 0.5, 0.5333333333333333, 0.4666666666666667, 0.4666666666666667, 0.4666666666666667, 0.4666666666666667, 0.36666666666666664, 0.36666666666666664, 0.43333333333333335, 0.5, 0.5333333333333333, 0.5333333333333333, 0.6333333333333333, 0.43333333333333335, 0.6, 0.6, 0.5666666666666667, 0.4, 0.4, 0.6, 0.3333333333333333, 0.4, 0.5, 0.5333333333333333, 0.4666666666666667, 0.5, 0.6, 0.4666666666666667, 0.5, 0.4, 0.4, 0.6333333333333333, 0.6, 0.4666666666666667, 0.5666666666666667, 0.5, 0.4666666666666667, 0.5333333333333333, 0.6333333333333333, 0.5333333333333333, 0.5666666666666667, 0.4666666666666667, 0.6333333333333333, 0.5, 0.4666666666666667, 0.6333333333333333, 0.4666666666666667, 0.5333333333333333, 0.5666666666666667, 0.6, 0.26666666666666666, 0.4, 0.5666666666666667, 0.7, 0.5, 0.5333333333333333, 0.6, 0.5333333333333333, 0.6, 0.36666666666666664, 0.4, 0.5666666666666667, 0.4666666666666667, 0.5333333333333333, 0.6, 0.36666666666666664, 0.3, 0.3333333333333333, 0.5333333333333333, 0.36666666666666664, 0.5, 0.6333333333333333, 0.7666666666666667, 0.6333333333333333, 0.5666666666666667, 0.5, 0.5333333333333333, 0.4666666666666667, 0.36666666666666664, 0.5666666666666667, 0.36666666666666664, 0.5, 0.5333333333333333, 0.3333333333333333, 0.5, 0.5333333333333333, 0.4, 0.6333333333333333, 0.5666666666666667, 0.5333333333333333, 0.43333333333333335, 0.4666666666666667, 0.6, 0.5666666666666667, 0.4666666666666667, 0.43333333333333335, 0.36666666666666664, 0.5, 0.6666666666666666, 0.5, 0.5333333333333333, 0.4, 0.5, 0.6, 0.43333333333333335, 0.5333333333333333, 0.43333333333333335, 0.5666666666666667, 0.6333333333333333, 0.43333333333333335, 0.5333333333333333, 0.4666666666666667, 0.4666666666666667, 0.6, 0.36666666666666664, 0.6, 0.7666666666666667, 0.36666666666666664, 0.4666666666666667, 0.5, 0.5, 0.43333333333333335, 0.5, 0.43333333333333335, 0.5333333333333333, 0.36666666666666664, 0.5666666666666667, 0.6, 0.4666666666666667, 0.36666666666666664, 0.5666666666666667, 0.5333333333333333, 0.43333333333333335, 0.5, 0.36666666666666664, 0.5666666666666667, 0.36666666666666664, 0.3333333333333333, 0.6, 0.6, 0.43333333333333335, 0.43333333333333335, 0.4666666666666667, 0.5666666666666667, 0.5, 0.5666666666666667, 0.6, 0.5666666666666667, 0.6333333333333333, 0.3, 0.4666666666666667, 0.6333333333333333, 0.5333333333333333, 0.4, 0.4666666666666667, 0.6333333333333333, 0.6333333333333333, 0.6333333333333333, 0.3333333333333333, 0.5333333333333333, 0.5333333333333333, 0.3333333333333333, 0.5333333333333333, 0.43333333333333335, 0.5333333333333333, 0.4666666666666667, 0.5, 0.5333333333333333, 0.5, 0.6333333333333333, 0.5, 0.5, 0.6333333333333333, 0.5333333333333333, 0.5666666666666667, 0.4666666666666667, 0.4666666666666667, 0.4, 0.5, 0.43333333333333335, 0.4, 0.4, 0.4, 0.4666666666666667, 0.4, 0.4, 0.5, 0.36666666666666664, 0.43333333333333335, 0.7, 0.43333333333333335, 0.4, 0.43333333333333335, 0.5, 0.4666666666666667, 0.7, 0.4, 0.3333333333333333, 0.5, 0.5, 0.5, 0.5333333333333333, 0.4, 0.4, 0.4666666666666667, 0.43333333333333335, 0.36666666666666664, 0.4666666666666667, 0.6, 0.5333333333333333, 0.5333333333333333, 0.5, 0.5333333333333333, 0.4, 0.6, 0.5, 0.4, 0.5666666666666667, 0.6666666666666666, 0.5666666666666667, 0.5333333333333333, 0.4666666666666667, 0.43333333333333335, 0.36666666666666664, 0.6333333333333333, 0.6, 0.8, 0.4666666666666667, 0.5333333333333333, 0.5333333333333333, 0.5, 0.5666666666666667, 0.6333333333333333, 0.5666666666666667, 0.4666666666666667, 0.5666666666666667, 0.4666666666666667, 0.6, 0.6, 0.43333333333333335, 0.6, 0.5, 0.7, 0.6333333333333333, 0.5, 0.5666666666666667, 0.6666666666666666, 0.5666666666666667, 0.5333333333333333, 0.5, 0.5, 0.5666666666666667, 0.43333333333333335, 0.36666666666666664, 0.5333333333333333, 0.5333333333333333, 0.5333333333333333, 0.5, 0.6, 0.6666666666666666, 0.5, 0.43333333333333335, 0.43333333333333335, 0.6333333333333333, 0.6, 0.6, 0.5666666666666667, 0.5, 0.5333333333333333, 0.36666666666666664, 0.43333333333333335, 0.5, 0.5333333333333333, 0.5333333333333333, 0.4666666666666667, 0.43333333333333335, 0.5333333333333333, 0.5333333333333333, 0.5, 0.6333333333333333, 0.43333333333333335, 0.5333333333333333, 0.6, 0.3, 0.5333333333333333, 0.6333333333333333, 0.4666666666666667, 0.6, 0.5666666666666667, 0.3333333333333333, 0.4666666666666667, 0.5666666666666667, 0.43333333333333335, 0.5333333333333333, 0.3333333333333333, 0.6333333333333333, 0.6, 0.5333333333333333, 0.4666666666666667, 0.43333333333333335, 0.43333333333333335, 0.4666666666666667, 0.5666666666666667, 0.6, 0.7, 0.43333333333333335, 0.5, 0.5, 0.43333333333333335, 0.7333333333333333, 0.43333333333333335, 0.5, 0.4666666666666667, 0.5, 0.4666666666666667, 0.4, 0.4666666666666667, 0.5, 0.4666666666666667, 0.5666666666666667, 0.43333333333333335, 0.5, 0.5, 0.4, 0.4666666666666667, 0.6, 0.4666666666666667, 0.5, 0.36666666666666664, 0.4666666666666667, 0.5, 0.4, 0.5666666666666667, 0.4666666666666667, 0.5333333333333333, 0.5, 0.4, 0.5333333333333333, 0.6, 0.5, 0.4, 0.4666666666666667, 0.36666666666666664, 0.6, 0.4666666666666667, 0.5333333333333333, 0.5, 0.5666666666666667, 0.4666666666666667, 0.36666666666666664, 0.3, 0.5, 0.43333333333333335, 0.6666666666666666, 0.3333333333333333, 0.4, 0.5333333333333333, 0.4666666666666667, 0.43333333333333335, 0.4, 0.6, 0.4666666666666667, 0.5, 0.3, 0.6333333333333333, 0.5666666666666667, 0.43333333333333335, 0.5, 0.36666666666666664, 0.43333333333333335, 0.6666666666666666, 0.4, 0.5, 0.5666666666666667, 0.5, 0.43333333333333335, 0.5333333333333333, 0.43333333333333335, 0.4, 0.5666666666666667, 0.36666666666666664, 0.5, 0.7, 0.4666666666666667, 0.5666666666666667, 0.43333333333333335, 0.5333333333333333, 0.43333333333333335, 0.36666666666666664, 0.6333333333333333, 0.6, 0.5, 0.4666666666666667, 0.6666666666666666, 0.5333333333333333, 0.43333333333333335, 0.36666666666666664, 0.4666666666666667, 0.43333333333333335, 0.6666666666666666, 0.5333333333333333, 0.5, 0.5, 0.6, 0.4, 0.43333333333333335, 0.5333333333333333, 0.6333333333333333, 0.6666666666666666, 0.5666666666666667, 0.6, 0.3333333333333333, 0.5666666666666667, 0.43333333333333335, 0.5666666666666667, 0.6333333333333333, 0.43333333333333335, 0.5, 0.6333333333333333, 0.5666666666666667, 0.5, 0.7333333333333333, 0.43333333333333335, 0.5333333333333333, 0.4666666666666667, 0.4666666666666667, 0.4666666666666667, 0.5666666666666667, 0.5666666666666667, 0.6, 0.4666666666666667, 0.3333333333333333, 0.4666666666666667, 0.36666666666666664, 0.4, 0.4, 0.5, 0.43333333333333335, 0.4666666666666667, 0.5666666666666667, 0.5333333333333333, 0.6, 0.6, 0.4666666666666667, 0.5333333333333333, 0.5666666666666667, 0.5, 0.7333333333333333, 0.4666666666666667, 0.36666666666666664, 0.4666666666666667, 0.6, 0.6666666666666666, 0.5333333333333333, 0.5333333333333333, 0.5333333333333333, 0.4, 0.6666666666666666, 0.36666666666666664, 0.43333333333333335, 0.4666666666666667, 0.4, 0.5666666666666667, 0.4, 0.4666666666666667, 0.4666666666666667, 0.4, 0.36666666666666664, 0.5, 0.5333333333333333, 0.5333333333333333, 0.5, 0.5666666666666667, 0.5333333333333333, 0.36666666666666664, 0.43333333333333335, 0.4666666666666667, 0.43333333333333335, 0.26666666666666666, 0.5666666666666667, 0.43333333333333335, 0.5666666666666667, 0.4666666666666667, 0.43333333333333335, 0.5, 0.6, 0.5333333333333333, 0.3333333333333333, 0.5, 0.43333333333333335, 0.6333333333333333, 0.5333333333333333, 0.5, 0.6333333333333333, 0.5333333333333333, 0.43333333333333335, 0.6, 0.5, 0.5333333333333333, 0.5333333333333333, 0.5333333333333333, 0.5666666666666667, 0.3333333333333333, 0.5, 0.5666666666666667, 0.5333333333333333, 0.4666666666666667, 0.5333333333333333, 0.5, 0.6, 0.36666666666666664, 0.3333333333333333, 0.4666666666666667, 0.43333333333333335, 0.43333333333333335, 0.7, 0.5333333333333333, 0.5333333333333333, 0.6, 0.5333333333333333, 0.5, 0.4666666666666667, 0.5333333333333333, 0.4666666666666667, 0.5666666666666667, 0.3333333333333333, 0.4666666666666667, 0.5333333333333333, 0.5666666666666667, 0.6, 0.4666666666666667, 0.43333333333333335, 0.5666666666666667, 0.36666666666666664, 0.6666666666666666, 0.36666666666666664, 0.43333333333333335, 0.43333333333333335, 0.5333333333333333, 0.5333333333333333, 0.5666666666666667, 0.5666666666666667, 0.5, 0.5333333333333333, 0.5333333333333333, 0.43333333333333335, 0.43333333333333335, 0.5, 0.4666666666666667, 0.6, 0.5, 0.6333333333333333, 0.5666666666666667, 0.5666666666666667, 0.4666666666666667, 0.4666666666666667, 0.5333333333333333, 0.43333333333333335, 0.43333333333333335, 0.3333333333333333, 0.43333333333333335, 0.4666666666666667, 0.36666666666666664, 0.3333333333333333, 0.4666666666666667, 0.36666666666666664, 0.5, 0.36666666666666664, 0.5333333333333333, 0.4666666666666667, 0.36666666666666664, 0.4666666666666667, 0.5666666666666667, 0.5, 0.6666666666666666, 0.4666666666666667, 0.5333333333333333, 0.5, 0.4, 0.5333333333333333, 0.43333333333333335, 0.5, 0.5333333333333333, 0.4, 0.6, 0.43333333333333335, 0.5333333333333333, 0.6333333333333333, 0.5, 0.5666666666666667, 0.43333333333333335, 0.43333333333333335, 0.6, 0.5333333333333333, 0.4666666666666667, 0.4, 0.43333333333333335, 0.3333333333333333, 0.5, 0.43333333333333335, 0.43333333333333335, 0.6, 0.4666666666666667, 0.4666666666666667, 0.5666666666666667, 0.5333333333333333, 0.5333333333333333, 0.6666666666666666, 0.4, 0.4, 0.4, 0.4, 0.36666666666666664, 0.5666666666666667, 0.6, 0.5333333333333333, 0.5666666666666667, 0.5, 0.6333333333333333, 0.4666666666666667, 0.5333333333333333, 0.6, 0.5333333333333333, 0.6, 0.36666666666666664, 0.4, 0.5, 0.43333333333333335, 0.43333333333333335, 0.36666666666666664, 0.5, 0.6333333333333333, 0.36666666666666664, 0.4, 0.3333333333333333, 0.7, 0.5333333333333333, 0.5, 0.5666666666666667, 0.36666666666666664, 0.4666666666666667, 0.43333333333333335, 0.4, 0.6]

```
# Create dataframe with single coin flip
df = pd.DataFrame({'one-sample': one_sample})
df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>one-sample</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>1</td>
    </tr>
    <tr>
      <th>1</th>
      <td>1</td>
    </tr>
    <tr>
      <th>2</th>
      <td>0</td>
    </tr>
    <tr>
      <th>3</th>
      <td>0</td>
    </tr>
    <tr>
      <th>4</th>
      <td>0</td>
    </tr>
  </tbody>
</table>
</div>

```
# Plot histogram to look at distribution of a single coin flip
df.hist()
```

```
# Plot histogram to look at distribution of all coin flips
ax = plt.hist(sample_means);
plt.title(f'Distribution of {N} Sample Means \n (of 30 coin flips each)');
```

What does the Central Limit Theorem State? That no matter the initial distribution of the population, the distribution of sample means taken will approximate a normal distribution as $n \rightarrow \infty$.

This has very important implications for hypothesis testing and is precisely the reason why the t-distribution begins to approximate the normal distribution as our sample size increases.

## Standard Error of the Mean

What does it mean to "estimate"? the Population mean?

```
import numpy as np
import pandas as pd

# Average Height
mu = 70
sigma = 3

lambda_heights = np.random.normal(mu, sigma, 2000)
print(len(lambda_heights))
lambda_heights
```

    2000

    array([70.11815382, 67.35684164, 70.92353897, ..., 70.87094828,
           69.71024776, 71.23370434])

```
import seaborn as sns

sns.distplot(lambda_heights)
plt.title('Distribution of Heights (in inches)');
```

```
print("Population Mean:", lambda_heights.mean())
print("Population Standard Deviation:", lambda_heights.std())
```

    Population Mean: 70.03529323187198
    Population Standard Deviation: 2.9478658567431717

```
population = pd.DataFrame({'heights': lambda_heights})
print(population.shape)
population.head()
```

    (2000, 1)

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>heights</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>70.118154</td>
    </tr>
    <tr>
      <th>1</th>
      <td>67.356842</td>
    </tr>
    <tr>
      <th>2</th>
      <td>70.923539</td>
    </tr>
    <tr>
      <th>3</th>
      <td>70.359457</td>
    </tr>
    <tr>
      <th>4</th>
      <td>75.110343</td>
    </tr>
  </tbody>
</table>
</div>

```
# Take a random sample and print sample mean
sample1 = population.sample(100)
print(sample1.shape)
sample1.head()
```

    (100, 1)

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>heights</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>52</th>
      <td>67.744768</td>
    </tr>
    <tr>
      <th>57</th>
      <td>70.670342</td>
    </tr>
    <tr>
      <th>805</th>
      <td>69.383068</td>
    </tr>
    <tr>
      <th>984</th>
      <td>65.749005</td>
    </tr>
    <tr>
      <th>924</th>
      <td>64.085916</td>
    </tr>
  </tbody>
</table>
</div>

```
print('Sample Mean #1:', sample1['heights'].mean())
```

    Sample Mean #1: 69.97166217126907

```
# Take a different random sample and print sample mean
sample2 = population.sample(100)
print(sample2.shape)
sample2.head()
```

    (100, 1)

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>heights</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>24</th>
      <td>70.216663</td>
    </tr>
    <tr>
      <th>1446</th>
      <td>65.790529</td>
    </tr>
    <tr>
      <th>947</th>
      <td>68.096752</td>
    </tr>
    <tr>
      <th>1113</th>
      <td>71.436505</td>
    </tr>
    <tr>
      <th>1403</th>
      <td>71.022002</td>
    </tr>
  </tbody>
</table>
</div>

```
print('Sample Mean #2:', sample2['heights'].mean())
```

    Sample Mean #2: 69.85254395335663

## Build and Interpret a Confidence Interval

```
coinflips_100 = np.random.binomial(n=1, p=0.5, size=100)

sample_std = np.std(coinflips_100)
print('Sample St Dev:', sample_std)
sample_size = len(coinflips_100)
print('Sample Size:', sample_size)
```

    Sample St Dev: 0.49355850717012273
    Sample Size: 100

```
standard_error = sample_std / np.sqrt(sample_size)
print(standard_error)
```

    0.049355850717012276

### What confidence level do we want our confidence interval to represent?

95% confidence Interval? 99% confidence interval?

```
import scipy.stats as stats
t = stats.t.ppf(0.975, sample_size-1)
t
```

    1.9842169515086827

```
sample_mean = coinflips_100.mean()
confidence_interval = (sample_mean - t *  sample_std / np.sqrt(sample_size), sample_mean + t * sample_std / np.sqrt(sample_size))
confidence_interval
```

    (0.48206728435117224, 0.6779327156488277)

## Graphically Represent a Confidence Interval

```
import seaborn as sns
sns.kdeplot(coinflips_100)
plt.axvline(x=sample_mean, color='k')
plt.axvline(x=confidence_interval[0], color='r')
plt.axvline(x=confidence_interval[1], color='r')
```

## Relationship between Confidence Intervals and T-tests

Confidence Interval == Bounds of statistical significance for our t-test

A sample mean that falls inside of our confidence interval will "FAIL TO REJECT" our null hypothesis

A sample mean that falls outside of our confidence interval will "REJECT" our null hypothesis

```
from scipy.stats import t, ttest_1samp
```

```
import numpy as np

coinflip_means = []
for x in range(0,100):
  coinflips = np.random.binomial(n=1, p=.5, size=30)
  coinflip_means.append(coinflips.mean())

print(coinflip_means)
```

    [0.6, 0.4666666666666667, 0.3333333333333333, 0.5333333333333333, 0.5, 0.5, 0.43333333333333335, 0.43333333333333335, 0.5333333333333333, 0.4666666666666667, 0.6, 0.5333333333333333, 0.43333333333333335, 0.43333333333333335, 0.5, 0.6, 0.43333333333333335, 0.43333333333333335, 0.3, 0.5666666666666667, 0.5, 0.5333333333333333, 0.43333333333333335, 0.5666666666666667, 0.43333333333333335, 0.4666666666666667, 0.4666666666666667, 0.4666666666666667, 0.6, 0.3333333333333333, 0.6, 0.3333333333333333, 0.6, 0.5333333333333333, 0.7333333333333333, 0.6666666666666666, 0.5, 0.43333333333333335, 0.4, 0.5333333333333333, 0.6666666666666666, 0.3, 0.5, 0.6666666666666666, 0.4, 0.5, 0.4666666666666667, 0.43333333333333335, 0.43333333333333335, 0.5, 0.6, 0.5, 0.43333333333333335, 0.5666666666666667, 0.4666666666666667, 0.5, 0.5666666666666667, 0.4666666666666667, 0.5, 0.5, 0.6, 0.6666666666666666, 0.5666666666666667, 0.6666666666666666, 0.4666666666666667, 0.5, 0.5, 0.6333333333333333, 0.5, 0.5666666666666667, 0.5666666666666667, 0.6666666666666666, 0.5666666666666667, 0.4666666666666667, 0.36666666666666664, 0.5, 0.4666666666666667, 0.5666666666666667, 0.36666666666666664, 0.5666666666666667, 0.36666666666666664, 0.5, 0.4666666666666667, 0.43333333333333335, 0.5666666666666667, 0.5333333333333333, 0.4666666666666667, 0.5, 0.5666666666666667, 0.5333333333333333, 0.5666666666666667, 0.4666666666666667, 0.5, 0.5, 0.5333333333333333, 0.5666666666666667, 0.4, 0.6, 0.6, 0.5333333333333333]

```
# 95% CI
t_stat = stats.t.ppf(0.975, 100 - 1)
t_stat

std_sample = np.std(coinflip_means)
std_err = std_sample / np.sqrt(len(coinflip_means))
```

```
CI = stats.t.interval(0.95, 100 - 1, loc = np.mean(coinflip_means), scale = std_err)
CI
```

    (0.4900779651914852, 0.5239220348085147)

A null hypothesis that's just inside of our confidence interval == fail to reject

```
ttest_1samp(coinflip_means, 0.491)
```

    Ttest_1sampResult(statistic=1.8666983838153832, pvalue=0.06490312631620906)

A null hypothesis that's just outside of our confidence interval == reject

```
ttest_1samp(coinflip_means, 0.489)
```

    Ttest_1sampResult(statistic=2.100035681792306, pvalue=0.038267638339196136)

```
def confidence_interval(data, confidence=0.95):
  """
  Calculate a confidence interval around a sample mean for given data.
  Using t-distribution and two-tailed test, default 95% confidence.

  Arguments:
    data - iterable (list or numpy array) of sample observations
    confidence - level of confidence for the interval

  Returns:
    tuple of (mean, lower bound, upper bound)
  """
  data = np.array(data)
  mean = np.mean(data)
  n = len(data)
  stderr = stats.sem(data)
  interval = stderr * stats.t.ppf((1 + confidence) / 2.0, n - 1)
  return (mean, mean - interval, mean + interval)
```

## Run a $\chi^{2}$ Test "by hand" (Using Numpy)

```
df = pd.read_csv('https://raw.githubusercontent.com/ryanleeallred/datasets/master/adult.csv', na_values=" ?")
print(df.shape)
df.head()
```

    (32561, 15)

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>age</th>
      <th>workclass</th>
      <th>fnlwgt</th>
      <th>education</th>
      <th>education-num</th>
      <th>marital-status</th>
      <th>occupation</th>
      <th>relationship</th>
      <th>race</th>
      <th>sex</th>
      <th>capital-gain</th>
      <th>capital-loss</th>
      <th>hours-per-week</th>
      <th>country</th>
      <th>salary</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>39</td>
      <td>State-gov</td>
      <td>77516</td>
      <td>Bachelors</td>
      <td>13</td>
      <td>Never-married</td>
      <td>Adm-clerical</td>
      <td>Not-in-family</td>
      <td>White</td>
      <td>Male</td>
      <td>2174</td>
      <td>0</td>
      <td>40</td>
      <td>United-States</td>
      <td><=50K</td>
    </tr>
    <tr>
      <th>1</th>
      <td>50</td>
      <td>Self-emp-not-inc</td>
      <td>83311</td>
      <td>Bachelors</td>
      <td>13</td>
      <td>Married-civ-spouse</td>
      <td>Exec-managerial</td>
      <td>Husband</td>
      <td>White</td>
      <td>Male</td>
      <td>0</td>
      <td>0</td>
      <td>13</td>
      <td>United-States</td>
      <td><=50K</td>
    </tr>
    <tr>
      <th>2</th>
      <td>38</td>
      <td>Private</td>
      <td>215646</td>
      <td>HS-grad</td>
      <td>9</td>
      <td>Divorced</td>
      <td>Handlers-cleaners</td>
      <td>Not-in-family</td>
      <td>White</td>
      <td>Male</td>
      <td>0</td>
      <td>0</td>
      <td>40</td>
      <td>United-States</td>
      <td><=50K</td>
    </tr>
    <tr>
      <th>3</th>
      <td>53</td>
      <td>Private</td>
      <td>234721</td>
      <td>11th</td>
      <td>7</td>
      <td>Married-civ-spouse</td>
      <td>Handlers-cleaners</td>
      <td>Husband</td>
      <td>Black</td>
      <td>Male</td>
      <td>0</td>
      <td>0</td>
      <td>40</td>
      <td>United-States</td>
      <td><=50K</td>
    </tr>
    <tr>
      <th>4</th>
      <td>28</td>
      <td>Private</td>
      <td>338409</td>
      <td>Bachelors</td>
      <td>13</td>
      <td>Married-civ-spouse</td>
      <td>Prof-specialty</td>
      <td>Wife</td>
      <td>Black</td>
      <td>Female</td>
      <td>0</td>
      <td>0</td>
      <td>40</td>
      <td>Cuba</td>
      <td><=50K</td>
    </tr>
  </tbody>
</table>
</div>

```
df['hours-per-week'].hist();
```

```
df.describe(exclude='number')
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>workclass</th>
      <th>education</th>
      <th>marital-status</th>
      <th>occupation</th>
      <th>relationship</th>
      <th>race</th>
      <th>sex</th>
      <th>country</th>
      <th>salary</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>count</th>
      <td>30725</td>
      <td>32561</td>
      <td>32561</td>
      <td>30718</td>
      <td>32561</td>
      <td>32561</td>
      <td>32561</td>
      <td>31978</td>
      <td>32561</td>
    </tr>
    <tr>
      <th>unique</th>
      <td>8</td>
      <td>16</td>
      <td>7</td>
      <td>14</td>
      <td>6</td>
      <td>5</td>
      <td>2</td>
      <td>41</td>
      <td>2</td>
    </tr>
    <tr>
      <th>top</th>
      <td>Private</td>
      <td>HS-grad</td>
      <td>Married-civ-spouse</td>
      <td>Prof-specialty</td>
      <td>Husband</td>
      <td>White</td>
      <td>Male</td>
      <td>United-States</td>
      <td><=50K</td>
    </tr>
    <tr>
      <th>freq</th>
      <td>22696</td>
      <td>10501</td>
      <td>14976</td>
      <td>4140</td>
      <td>13193</td>
      <td>27816</td>
      <td>21790</td>
      <td>29170</td>
      <td>24720</td>
    </tr>
  </tbody>
</table>
</div>

```
cut_points = [0, 9, 19, 29, 39, 49, 500]
label_names = ['0-9', '10-19', '20-29', '30-39', '40-49', '50 and over']
df['hours_per_week_categories'] = pd.cut(df['hours-per-week'], cut_points, labels=label_names)
df.hours_per_week_categories.value_counts()
```

    40-49          18336
    50 and over     6462
    30-39           3667
    20-29           2392
    10-19           1246
    0-9              458
    Name: hours_per_week_categories, dtype: int64

```
df.sex.value_counts()
```

     Male      21790
     Female    10771
    Name: sex, dtype: int64

```
df = df.sort_values(by='hours_per_week_categories', ascending=True)
contingency_table = pd.crosstab(df['sex'], df['hours_per_week_categories'], margins=True)
contingency_table
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th>hours_per_week_categories</th>
      <th>0-9</th>
      <th>10-19</th>
      <th>20-29</th>
      <th>30-39</th>
      <th>40-49</th>
      <th>50 and over</th>
      <th>All</th>
    </tr>
    <tr>
      <th>sex</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>Female</th>
      <td>235</td>
      <td>671</td>
      <td>1287</td>
      <td>1914</td>
      <td>5636</td>
      <td>1028</td>
      <td>10771</td>
    </tr>
    <tr>
      <th>Male</th>
      <td>223</td>
      <td>575</td>
      <td>1105</td>
      <td>1753</td>
      <td>12700</td>
      <td>5434</td>
      <td>21790</td>
    </tr>
    <tr>
      <th>All</th>
      <td>458</td>
      <td>1246</td>
      <td>2392</td>
      <td>3667</td>
      <td>18336</td>
      <td>6462</td>
      <td>32561</td>
    </tr>
  </tbody>
</table>
</div>

```

```

## Expected Value Calculation
\begin{align}
expected_{i,j} =\frac{(row_{i} \text{total})(column_{j} \text{total}) }{(\text{total observations})}
\end{align}

```
row_sums = contingency_table.iloc[0:2, 6].values
col_sums = contingency_table.iloc[2, 0:6].values

print(row_sums)
print(col_sums)
```

    [10771 21790]
    [  458  1246  2392  3667 18336  6462]

```
total = contingency_table.loc['All', 'All']
print(total)
```

    32561

```
expected = []
for i in range(len(row_sums)):
  expected_row = []
  for column in col_sums:
    expected_val = column * row_sums[i] / total
    expected_row.append(expected_val)

  expected.append(expected_row)

expected = np.array(expected)
print(expected.shape)
print(expected)
```

    (2, 6)
    [[  151.50388502   412.16995793   791.26046497  1213.02346365
       6065.44811277  2137.59411566]
     [  306.49611498   833.83004207  1600.73953503  2453.97653635
      12270.55188723  4324.40588434]]

```
contingency_table
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th>hours_per_week_categories</th>
      <th>0-9</th>
      <th>10-19</th>
      <th>20-29</th>
      <th>30-39</th>
      <th>40-49</th>
      <th>50 and over</th>
      <th>All</th>
    </tr>
    <tr>
      <th>sex</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>Female</th>
      <td>235</td>
      <td>671</td>
      <td>1287</td>
      <td>1914</td>
      <td>5636</td>
      <td>1028</td>
      <td>10771</td>
    </tr>
    <tr>
      <th>Male</th>
      <td>223</td>
      <td>575</td>
      <td>1105</td>
      <td>1753</td>
      <td>12700</td>
      <td>5434</td>
      <td>21790</td>
    </tr>
    <tr>
      <th>All</th>
      <td>458</td>
      <td>1246</td>
      <td>2392</td>
      <td>3667</td>
      <td>18336</td>
      <td>6462</td>
      <td>32561</td>
    </tr>
  </tbody>
</table>
</div>

```
observed = pd.crosstab(df['sex'], df['hours_per_week_categories']).values
```

## Chi-Squared Statistic with Numpy

\begin{align}
\chi^2 = \sum \frac{(observed_{i}-expected_{i})^2}{(expected_{i})}
\end{align}

For the $observed$ values we will just use a version of our contingency table without the margins as a numpy array. In this way, if our observed values array and our expected values array are the same shape, then we can subtract them and divide them directly which makes the calculations a lot cleaner. No for loops!

```
chi_square = ((observed - expected) ** 2/(expected)).sum()
chi_square
```

    2287.190943926107

## Run a $\chi^{2}$ Test using Scipy

```
chi_squared, p_value, dof, expected = stats.chi2_contingency(observed)
print(p_value)
```

    0.0

Null Hypothesis: Hours worked per week bins is **independent** of sex.

Due to a p-value of 0, we REJECT the null hypothesis that hours worked per week and sex are independent, and conclude that there is an association between hours worked per week and sex.

## Assignment - Build a confidence interval

A confidence interval refers to a neighborhood around some point estimate, the size of which is determined by the desired p-value. For instance, we might say that 52% of Americans prefer tacos to burritos, with a 95% confidence interval of +/- 5%.

52% (0.52) is the point estimate, and +/- 5% (the interval $[0.47, 0.57]$) is the confidence interval. "95% confidence" means a p-value $\leq 1 - 0.95 = 0.05$.

In this case, the confidence interval includes $0.5$ - which is the natural null hypothesis (that half of Americans prefer tacos and half burritos, thus there is no clear favorite). So in this case, we could use the confidence interval to report that we've failed to reject the null hypothesis.

But providing the full analysis with a confidence interval, including a graphical representation of it, can be a helpful and powerful way to tell your story. Done well, it is also more intuitive to a layperson than simply saying "fail to reject the null hypothesis" - it shows that in fact the data does *not* give a single clear result (the point estimate) but a whole range of possibilities.

How is a confidence interval built, and how should it be interpreted? It does *not* mean that 95% of the data lies in that interval - instead, the frequentist interpretation is "if we were to repeat this experiment 100 times, we would expect the average result to lie in this interval ~95 times."

For a 95% confidence interval and a normal(-ish) distribution, you can simply remember that +/-2 standard deviations contains 95% of the probability mass, and so the 95% confidence interval based on a given sample is centered at the mean (point estimate) and has a range of +/- 2 (or technically 1.96) standard deviations.

Different distributions/assumptions (90% confidence, 99% confidence) will require different math, but the overall process and interpretation (with a frequentist approach) will be the same.

Your assignment - using the data from the prior module ([congressional voting records](https://archive.ics.uci.edu/ml/datasets/Congressional+Voting+Records)):

### Confidence Intervals:
1. Generate and numerically represent a confidence interval
2. Graphically (with a plot) represent the confidence interval
3. Interpret the confidence interval - what does it tell you about the data and its distribution?

### Chi-squared tests:
4. Take a dataset that we have used in the past in class that has **categorical** variables. Pick two of those categorical variables and run a chi-squared tests on that data
  - By hand using Numpy
  - In a single line using Scipy

Stretch goals:

1. Write a summary of your findings, mixing prose and math/code/results. *Note* - yes, this is by definition a political topic. It is challenging but important to keep your writing voice *neutral* and stick to the facts of the data. Data science often involves considering controversial issues, so it's important to be sensitive about them (especially if you want to publish).
2. Apply the techniques you learned today to your project data or other data of your choice, and write/discuss your findings here.
3. Refactor your code so it is elegant, readable, and can be easily run for all issues.

```
# TODO - your code!
import pandas as pd

columns = [
  'class-name',
  'handicapped-infants',
  'water-project-cost-sharing',
  'adoption-of-the-budget-resolution',
  'physician-fee-freeze',
  'el-salvador-aid',
  'religious-groups-in-schools',
  'anti-satellite-test-ban',
  'aid-to-nicaraguan-contras',
  'mx-missile',
  'immigration',
  'synfuels-corporation-cutback',
  'education-spending',
  'superfund-right-to-sue',
  'crime',
  'duty-free-exports',
  'export-administration-act-south-africa',
]

df = pd.read_csv(
    'https://raw.githubusercontent.com/danieljaouen/DS-Unit-1-Sprint-3-Statistical-Tests-and-Experiments/master/module1-statistics-probability-and-inference/house-votes-84.data',
    names=columns, na_values=['?']
)

print(df.shape)
df.head()
```

    (435, 17)

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>class-name</th>
      <th>handicapped-infants</th>
      <th>water-project-cost-sharing</th>
      <th>adoption-of-the-budget-resolution</th>
      <th>physician-fee-freeze</th>
      <th>el-salvador-aid</th>
      <th>religious-groups-in-schools</th>
      <th>anti-satellite-test-ban</th>
      <th>aid-to-nicaraguan-contras</th>
      <th>mx-missile</th>
      <th>immigration</th>
      <th>synfuels-corporation-cutback</th>
      <th>education-spending</th>
      <th>superfund-right-to-sue</th>
      <th>crime</th>
      <th>duty-free-exports</th>
      <th>export-administration-act-south-africa</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>republican</td>
      <td>n</td>
      <td>y</td>
      <td>n</td>
      <td>y</td>
      <td>y</td>
      <td>y</td>
      <td>n</td>
      <td>n</td>
      <td>n</td>
      <td>y</td>
      <td>NaN</td>
      <td>y</td>
      <td>y</td>
      <td>y</td>
      <td>n</td>
      <td>y</td>
    </tr>
    <tr>
      <th>1</th>
      <td>republican</td>
      <td>n</td>
      <td>y</td>
      <td>n</td>
      <td>y</td>
      <td>y</td>
      <td>y</td>
      <td>n</td>
      <td>n</td>
      <td>n</td>
      <td>n</td>
      <td>n</td>
      <td>y</td>
      <td>y</td>
      <td>y</td>
      <td>n</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>2</th>
      <td>democrat</td>
      <td>NaN</td>
      <td>y</td>
      <td>y</td>
      <td>NaN</td>
      <td>y</td>
      <td>y</td>
      <td>n</td>
      <td>n</td>
      <td>n</td>
      <td>n</td>
      <td>y</td>
      <td>n</td>
      <td>y</td>
      <td>y</td>
      <td>n</td>
      <td>n</td>
    </tr>
    <tr>
      <th>3</th>
      <td>democrat</td>
      <td>n</td>
      <td>y</td>
      <td>y</td>
      <td>n</td>
      <td>NaN</td>
      <td>y</td>
      <td>n</td>
      <td>n</td>
      <td>n</td>
      <td>n</td>
      <td>y</td>
      <td>n</td>
      <td>y</td>
      <td>n</td>
      <td>n</td>
      <td>y</td>
    </tr>
    <tr>
      <th>4</th>
      <td>democrat</td>
      <td>y</td>
      <td>y</td>
      <td>y</td>
      <td>n</td>
      <td>y</td>
      <td>y</td>
      <td>n</td>
      <td>n</td>
      <td>n</td>
      <td>n</td>
      <td>y</td>
      <td>NaN</td>
      <td>y</td>
      <td>y</td>
      <td>y</td>
      <td>y</td>
    </tr>
  </tbody>
</table>
</div>

```
df = df.replace({'y': 1, 'n': 0})
df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>class-name</th>
      <th>handicapped-infants</th>
      <th>water-project-cost-sharing</th>
      <th>adoption-of-the-budget-resolution</th>
      <th>physician-fee-freeze</th>
      <th>el-salvador-aid</th>
      <th>religious-groups-in-schools</th>
      <th>anti-satellite-test-ban</th>
      <th>aid-to-nicaraguan-contras</th>
      <th>mx-missile</th>
      <th>immigration</th>
      <th>synfuels-corporation-cutback</th>
      <th>education-spending</th>
      <th>superfund-right-to-sue</th>
      <th>crime</th>
      <th>duty-free-exports</th>
      <th>export-administration-act-south-africa</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>republican</td>
      <td>0.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>1.0</td>
      <td>NaN</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>1.0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>republican</td>
      <td>0.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>NaN</td>
    </tr>
    <tr>
      <th>2</th>
      <td>democrat</td>
      <td>NaN</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>NaN</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>0.0</td>
    </tr>
    <tr>
      <th>3</th>
      <td>democrat</td>
      <td>0.0</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>NaN</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>1.0</td>
    </tr>
    <tr>
      <th>4</th>
      <td>democrat</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>0.0</td>
      <td>1.0</td>
      <td>NaN</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>1.0</td>
      <td>1.0</td>
    </tr>
  </tbody>
</table>
</div>

```
df_immigration = df.copy()
df_immigration['immigration'].dropna(inplace=True)
df_immigration['immigration'].isna().sum()
```

    0

```
import numpy as np

df_immigration_republicans = df_immigration[df_immigration['class-name'] == 'republican']
sample_size = len(df_immigration_republicans)
mean = df_immigration_republicans['immigration'].mean()
std = df_immigration_republicans['immigration'].std()
std_err = std / np.sqrt(sample_size)

print(mean, std_err)
```

    0.5575757575757576 0.03843587804667872

```
import scipy.stats as stats
tstat = stats.t.ppf(0.975, sample_size - 1)
confidence_interval = (mean - tstat * std_err, mean + tstat * std_err)
print(confidence_interval)
```

    (0.4816929198405456, 0.6334585953109697)

```
import seaborn as sns
import matplotlib.pyplot as plt
sns.kdeplot(df_immigration_republicans['immigration']);
plt.axvline(x=mean, color='k');
plt.axvline(x=confidence_interval[0], color='r');
plt.axvline(x=confidence_interval[1], color='r');
plt.show()
```

## Resources

- [Interactive visualize the Chi-Squared test](https://homepage.divms.uiowa.edu/~mbognar/applets/chisq.html)
- [Calculation of Chi-Squared test statistic](https://en.wikipedia.org/wiki/Pearson%27s_chi-squared_test)
- [Visualization of a confidence interval generated by R code](https://commons.wikimedia.org/wiki/File:Confidence-interval.svg)
- [Expected value of a squared standard normal](https://math.stackexchange.com/questions/264061/expected-value-calculation-for-squared-normal-distribution) (it's 1 - which is why the expected value of a Chi-Squared with $n$ degrees of freedom is $n$, as it's the sum of $n$ squared standard normals)


Table of Contents

1  Objectives

2  Motivating  The Bayesian Classifier 🧐

2.1  Naive Bayes Setup

2.1.1  What's So Great About This?

2.2  The Naive Assumption

2.3  The Formula

2.3.1  What Parts Can We Find?

2.4  Calculating That Our Email Is Spam

2.5  Extending It With Multiple Words

3  Naive Bayes Modeling Example

3.1  Using Bayes's Theorem for Classification

3.1.1  Does this look like a classification problem?

3.2  Elephant Example

3.2.1  Naive Bayes by Hand

3.2.2  Calculation of Likelihoods

3.2.3  Posteriors

3.2.4  More Dimensions

3.2.4.1  What's "Naive" about This?

3.2.4.2  Posteriors

3.2.5  GaussianNB

3.3  Comma Survey Example

3.3.1  Calculating Priors and Likelihoods

3.3.2  Calculating Posteriors

3.3.3  Comparison with MultinomialNB

```python
import numpy as np
import pandas as pd
from scipy import stats
from sklearn.naive_bayes import MultinomialNB, GaussianNB
    # There is also a BernoulliNB for a dataset with binary predictors
import seaborn as sns
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import plot_confusion_matrix
from sklearn.preprocessing import OneHotEncoder

%matplotlib inline
```

# Objectives

- Describe how Bayes's Theorem can be used to make predictions of a target
- Identify the appropriate variant of Naive Bayes models for a particular business problem

# Motivating  The Bayesian Classifier 🧐

> Let's take a second to go through an example to get a feel for how Bayes' Theorem can help us with classification. Specifically about document classification

Spam, Spam, Spam, Spam, Spam...

> This is the classic example: detecting email spam!

**The Problem Setup**

> We get emails that can be either emails we care about (***ham*** 🐷) or emails we don't care about (***spam*** 🥫).
>
> We can probably look at the words in the email and get an idea of whether they are spam or not just by observing if they contain red-flag words 🚩
>
> We won't always be right, but if we see an email that uses word(s) that are more often associated with spam, then we can feel more confident as labeling that email as spam!

## Naive Bayes Setup

What we gotta do:

1. Look at spam and not spam (ham) emails
2. Identify words that suggest classification
3. Determine probability that words occur in each classification
4. Profit (classify new emails as "spam" or "ham")

### What's So Great About This?

- We can keep updating our belief based on the emails we detect
- Relatively simple
- Can expand to multiple words

## The Naive Assumption

$P(A,B) = P(A\cap B) = P(A)\ P(B)$ only if independent

In practice, makes sense & is usually pretty good assumption

## The Formula

Let's say the word that occurs is "cash":

$$ P(🥫 | "cash") = \frac{P("cash" | 🥫)P(🥫)}{P("cash")}$$

### What Parts Can We Find?

- $P("cash")$
    * That's just the probability of finding the word "cash"! Frequency of the word!
- $P(🥫)$
    * Well, we start with some data (_prior knowledge_). So frequency of the spam occurring!
- $P("cash" | 🥫)$
    * How frequently "cash" is used in known spam emails. Count the frequency across all spam emails

## Calculating That Our Email Is Spam

```python
# Let's just say 2% of all emails have the word "cash" in them
p_cash = 0.02

# We normally would measure this from our data, but we'll take
# it that 10% of all emails we collected were spam
p_spam = 0.10

# 12% of all spam emails have the word "cash"
p_cash_given_its_spam = 0.12
```

```python
p_spam_given_cash = p_cash_given_its_spam * p_spam / p_cash
print(f'If the email has the word "cash" in it, there is a \
{p_spam_given_cash*100}% chance the email is spam')
```

> **Check it**: Does this make sense?

> Suppose I had 250 total emails.
> - How many should I expect to have the word 'cash' in them? (Ans. 5)
> - How many should I expect to be spam? (Ans. 25)
> - How many *of the spam emails* should I expect to have the word 'cash' in them? (Ans. 3)

## Extending It With Multiple Words

> With more words, the more certain we can be if it is/isn't spam

Spam:

$$ P(🥫\ |"buy",\ "cash") \propto P("buy",\ "cash"|\ 🥫)\ P(🥫)$$

But because of independence:

$$ P("buy",\ "cash"|\ 🥫) = P("buy"|\ 🥫)\ P("cash"|\ 🥫)$$

Normalize by dividing!

$$
P(🥫\ |"buy",\ "cash")  =
    \frac
        {P("buy"|\ 🥫)P("cash"|\ 🥫)\ P(🥫)}
        {P("buy"|\ 🥫)P("cash"|\ 🥫)\ P(🥫) + P("buy"|\ 🐷)P("cash"|\ 🐷)\ P(🐷)}
$$

> **Note:** If we wanted to find the most probable class (especially useful for _multiclass_), we find the maximum numerator for the given criteria

# Naive Bayes Modeling Example

## Using Bayes's Theorem for Classification

Let's recall Bayes's Theorem:

$\large P(h|e) = \frac{P(h)P(e|h)}{P(e)}$

### Does this look like a classification problem?

- Suppose we have three competing hypotheses $\{h_1, h_2, h_3\}$ that would explain our evidence $e$.
    - Then we could use Bayes's Theorem to calculate the posterior probabilities for each of these three:
        - $P(h_1|e) = \frac{P(h_1)P(e|h_1)}{P(e)}$
        - $P(h_2|e) = \frac{P(h_2)P(e|h_2)}{P(e)}$
        - $P(h_3|e) = \frac{P(h_3)P(e|h_3)}{P(e)}$

- Suppose the evidence is a collection of elephant weights.
- Suppose each of the three hypotheses claims that the elephant whose measurements we have belongs to one of the three extant elephant species (*L. africana*, *L. cyclotis*, and *E. maximus*).

In that case the left-hand sides of these equations represent the probability that the elephant in question belongs to a given species.

If we think of the species as our target, then **this is just an ordinary classification problem**.

What about the right-hand sides of the equations? **These other probabilities we can calculate from our dataset.**

- The priors can simply be taken to be the percentages of the different classes in the dataset.
- What about the likelihoods?
    - If the relevant features are **categorical**, we can simply count the numbers of each category in the dataset. For example, if the features are whether the elephant has tusks or not, then, to calculate the likelihoods, we'll just count the tusked and non-tuksed elephants per species.
    - If the relevant features are **numerical**, we'll have to do something else. A good way of proceeding is to rely on (presumed) underlying distributions of the data. [Here](https://medium.com/analytics-vidhya/use-naive-bayes-algorithm-for-categorical-and-numerical-data-classification-935d90ab273f) is an example of using the normal distribution to calculate likelihoods. We'll follow this idea below for our elephant data.

## Elephant Example

Suppose we have a dataset that looks like this:

```python
elephs = pd.read_csv('data/elephants.csv', usecols=['height (cm)',
                                                   'species'])
```

```python
elephs.head()
```

```python
plt.style.use('fivethirtyeight')

fig, ax = plt.subplots()

sns.kdeplot(data=elephs[elephs['species'] == 'maximus']['height (cm)'],
            ax=ax, label='maximus')
sns.kdeplot(data=elephs[elephs['species'] == 'africana']['height (cm)'],
            ax=ax, label='africana')
sns.kdeplot(data=elephs[elephs['species'] == 'cyclotis']['height (cm)'],
            ax=ax, label='cyclotis');
```

### Naive Bayes by Hand

Suppose we want to make prediction of species for some new elephant whose weight we've just recorded. We'll suppose the new elephant has:

```python
new_ht = 263
```

What we want to calculate is the mean and standard deviation for height for each elephant species. We'll use these to calculate the relevant likelihoods.

So:

```python
max_stats = elephs[elephs['species'] == 'maximus'].describe().loc[['mean', 'std'], :]
max_stats
```

```python
cyc_stats = elephs[elephs['species'] == 'cyclotis'].describe().loc[['mean', 'std'], :]
cyc_stats
```

```python
afr_stats = elephs[elephs['species'] == 'africana'].describe().loc[['mean', 'std'], :]
afr_stats
```

```python
elephs['species'].value_counts()
```

### Calculation of Likelihoods

We'll use the PDFs of the normal distributions with the discovered means and standard deviations to calculate likelihoods:

```python
stats.norm(loc=max_stats['height (cm)'][0],
           scale=max_stats['height (cm)'][1]).pdf(263)
```

```python
stats.norm(loc=cyc_stats['height (cm)'][0],
          scale=cyc_stats['height (cm)'][1]).pdf(263)
```

```python
stats.norm(loc=afr_stats['height (cm)'][0],
          scale=afr_stats['height (cm)'][1]).pdf(263)
```

### Posteriors

What we have just calculated are (approximations of) the likelihoods, i.e.:

- $P(height=263 | species=maximus) = 2.04\%$
- $P(height=263 | species=cyclotis) = 1.50\%$
- $P(height=263 | species=africana) = 0.90\%$

(Notice that they do NOT sum to 1!) But what we'd really like to know are the posteriors. I.e. what are:

- $P(species=maximus | height=263)$?
- $P(species=cyclotis | height=263)$?
- $P(species=africana | height=263)$?

Since we have equal numbers of each species, every prior is equal to $\frac{1}{3}$. Thus we can calculate the probability of the evidence:

$P(height=263) = \frac{1}{3}(0.0204 + 0.0150 + 0.0090) = 0.0148$

And therefore calculate the posteriors using Bayes's Theorem:

- $P(species=maximus | height=263) = \frac{1}{3}\frac{0.0204}{0.0148} = 45.9\%$;
- $P(species=cyclotis | height=263) = \frac{1}{3}\frac{0.0150}{0.0148} = 33.8\%$;
- $P(species=africana | height=263) = \frac{1}{3}\frac{0.0090}{0.0148} = 20.3\%$.

Bayes's Theorem shows us that the largest posterior belongs to the *maximus* species. (Note also that, since the priors are all the same, the largest posterior will necessarily belong to the species with the largest likelihood!)

Therefore, the *maximus* species will be our prediction for an elephant of this height.

### More Dimensions

In fact, we also have elephant *weight* data available in addition to their heights. To accommodate multiple features we can make use of **multivariate normal** distributions.

#### What's "Naive" about This?

For multiple predictors, we make the simplifying assumption that **our predictors are probablistically independent**. This will often be unrealistic, but it simplifies our calculations a great deal.

```python
elephants = pd.read_csv('data/elephants.csv',
                       usecols=['height (cm)', 'weight (lbs)', 'species'])
```

```python
elephants.head()
```

```python
maximus = elephants[elephants['species'] == 'maximus']
cyclotis = elephants[elephants['species'] == 'cyclotis']
africana = elephants[elephants['species'] == 'africana']
```

Suppose our new elephant with a height of 263 cm also has a weight of 7009 lbs.

```python
likeli_max = stats.multivariate_normal(mean=maximus.mean(),
                          cov=maximus.cov()).pdf([263, 7009])
likeli_max
```

```python
likeli_cyc = stats.multivariate_normal(mean=cyclotis.mean(),
                         cov=cyclotis.cov()).pdf([263, 7009])
likeli_cyc
```

```python
likeli_afr = stats.multivariate_normal(mean=africana.mean(),
                         cov=africana.cov()).pdf([263, 7009])
likeli_afr
```

#### Posteriors

```python
post_max = likeli_max / sum([likeli_max, likeli_cyc, likeli_afr])
post_cyc = likeli_cyc / sum([likeli_max, likeli_cyc, likeli_afr])
post_afr = likeli_afr / sum([likeli_max, likeli_cyc, likeli_afr])

print(post_max)
print(post_cyc)
print(post_afr)
```

### [`GaussianNB`](https://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.GaussianNB.html)

```python
gnb = GaussianNB(priors=[1/3, 1/3, 1/3])
```

```python
X = elephants.drop('species', axis=1)
y = elephants['species']

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
gnb.fit(X_train, y_train)
```

```python
gnb.predict_proba(np.array([263, 7009]).reshape(1, -1))
```

```python
gnb.score(X_test, y_test)
```

```python
plot_confusion_matrix(gnb, X_test, y_test);
```

## Comma Survey Example

```python
commas = pd.read_csv('data/comma-survey.csv')
```

```python
commas.head()
```

The first question on the survey was about the Oxford comma.

```python
commas.isna().sum().sum()
```

We'll go ahead and drop the NaNs:

```python
commas = commas.dropna()
```

```python
commas.shape
```

```python
commas['In your opinion, which sentence is more gramatically correct?'].value_counts()
```

Personally, I like the Oxford comma, since it can help eliminate ambiguities, such as:

"This book is dedicated to my parents, Ayn Rand, and God"
 vs.

"This book is dedicated to my parents, Ayn Rand and God"

Let's see how a Naive Bayes model would make a prediction here. We'll think of the comma preference as our target.

```python
commas['Age'].value_counts()
```

Suppose we want to make a prediction about Oxford comma usage for a new person who falls into the **45-60 age group**.

### Calculating Priors and Likelihoods

The following code makes a table of values that count up the number of survey respondents who fall into each of eight bins (the four age groups and the two answers to the first comma question).

```python
table = np.zeros((2, 4))

for idx, value in enumerate(commas['Age'].value_counts().index):
    table[0, idx] = len(commas[(commas['In your opinion, which sentence is '\
                                       'more gramatically correct?'] ==\
                                        'It\'s important for a person to be '\
                                'honest, kind, and loyal.') & (commas['Age'] == value)])
    table[1, idx] = len(commas[(commas['In your opinion, which sentence is '\
                                       'more gramatically correct?'] ==\
                                        'It\'s important for a person to be '\
                                'honest, kind and loyal.') & (commas['Age'] == value)])
```

```python
table
```

```python
df = pd.DataFrame(table, columns=['Age45-60',
                            'Age>60',
                            'Age30-44',
                            'Age18-29'])
df
```

```python
df['Oxford'] = [True, False]
df = df[['Age>60', 'Age45-60', 'Age30-44', 'Age18-29', 'Oxford']]
df
```

Since all we have is a single categorical feature here we can just read our likelihoods and priors right off of this table:

Likelihoods:

- Age45-60:
    - P(Age45-60 | Oxford=True) = $\frac{123}{470} = 0.2617$;
    - P(Age45-60 | Oxford=False) = $\frac{125}{355} = 0.3521$.

Priors:

- P(Oxford=True) = $\frac{470}{825} = 0.5697$;
- P(Oxford=False) = $\frac{355}{825} = 0.4303$.

### Calculating Posteriors

First we'll calculate the probability of the evidence:

$$\begin{align}
    P(Age45-60) &= P(Age45-60 | Oxford=True) \cdot P(Oxford=True) \\
                & \hspace{1cm} + P(Age45-60 | Oxford=False) \cdot P(Oxford=False)\\
                &= 0.2617 \cdot 0.5697 + 0.3521 \cdot 0.4303 \\
                &= 0.3006
\end{align}$$

```python
(123+125)/825
```

Now use Bayes's Theorem to calculate the posteriors:

$$\begin{align}
P(Oxford=True | Age45-60) &= P(Oxford=True) \cdot P(Age45-60 | Oxford=True) / P(Age45-60) \\
                          &= 0.5697 \cdot 0.2617 / 0.3006 \\
                          &= 0.4960 \\
                          \\
P(Oxford=False | Age45-60) &= P(Oxford=False) \cdot P(Age45-60 | Oxford=False) / P(Age45-60) \\
                          &= 0.4303 \cdot 0.3521 / 0.3006 \\
                          &= 0.5040
\end{align}$$

Close! But our prediction for someone in the 45-60 age group will be that they **do not** favor the Oxford comma.

### Comparison with [`MultinomialNB`](https://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.MultinomialNB.html)

```python
comma_model = MultinomialNB()

ohe = OneHotEncoder()
ohe.fit(commas['Age'].values.reshape(-1, 1))

X = ohe.transform(commas['Age'].values.reshape(-1, 1)).todense()
y = commas['In your opinion, which sentence is more gramatically correct?']
```

```python
comma_model.fit(X, y)
```

```python
comma_model.predict_proba(np.array([0, 0, 1, 0]).reshape(1, -1))
```

```python

```