Probability#

In this chapter we will go over how to perform probability computations in Python.

Basic probability calculations#

Let’s create a vector of outcomes from one to 6, using the np.arange() function to create such a sequence. This function takes the minimum and maximum values as its inputs, but note that the maximum is not included in the sequence; that is, the sequence goes up to but not including the maximum. Thus, we would have to give 1 and 7 as the minimum and maximum in order to get a sequence of numbers from 1 to 6:

import numpy as np
outcomes = np.arange(1, 7)
print(outcomes)
[1 2 3 4 5 6]

Now let’s create a vector of logical values based on whether the outcome in each position is equal to 1. Remember that == tests for equality of each element in a vector:

outcome1isTrue = outcomes == 1
print(outcome1isTrue)
[ True False False False False False]

Remember that the simple probability of an outcome is number of occurrences of the outcome divided by the total number of events. To compute a probability, we can take advantage of the fact that TRUE/FALSE are equivalent to 1/0 in Python. The formula for the mean (sum of values divided by the number of values) is thus exactly the same as the formula for the simple probability! So, we can compute the probability of the event by simply taking the mean of the logical vector.

p1isTrue = np.mean(outcome1isTrue)
print(p1isTrue)
0.16666666666666666

Empirical frequency#

Let’s walk through how we computed empirical frequency of rain in San Francisco.

First we load the data:

#+
import pandas as pd
SFrain = pd.read_csv('https://raw.githubusercontent.com/statsthinking21/statsthinking21-python/master/notebooks/data/SanFranciscoRain.csv')

# we will remove the STATION and NAME variables
# since they are identical for all rows

SFrain = SFrain.drop(columns=['STATION', 'NAME'])
print(SFrain)
#-
           DATE  PRCP
0    2017-01-01  0.05
1    2017-01-02  0.10
2    2017-01-03  0.40
3    2017-01-04  0.89
4    2017-01-05  0.01
..          ...   ...
360  2017-12-27  0.00
361  2017-12-28  0.00
362  2017-12-29  0.00
363  2017-12-30  0.00
364  2017-12-31  0.00

[365 rows x 2 columns]

We see that the data frame contains a variable called PRCP which denotes the amount of rain each day. Let’s create a new variable called rainToday that denotes whether the amount of precipitation was above zero:

SFrain['rainToday'] = SFrain['PRCP'] > 0
print(SFrain)
           DATE  PRCP  rainToday
0    2017-01-01  0.05       True
1    2017-01-02  0.10       True
2    2017-01-03  0.40       True
3    2017-01-04  0.89       True
4    2017-01-05  0.01       True
..          ...   ...        ...
360  2017-12-27  0.00      False
361  2017-12-28  0.00      False
362  2017-12-29  0.00      False
363  2017-12-30  0.00      False
364  2017-12-31  0.00      False

[365 rows x 3 columns]

Now we will summarize the data to compute the probability of rain:

pRainInSF = SFrain['rainToday'].mean()
print(pRainInSF)
0.2

Conditional probability#

Let’s determine the conditional probability of someone having hearing problems, given that they are over 70 years of age, using the NHANES dataset. First, let’s create a new variable called Over70 that denotes whether each individual is over 70 or not.

! pip install nhanes
from nhanes.load import load_NHANES_data
nhanes_data = load_NHANES_data()

nhanes_data['Over70'] = nhanes_data['AgeInYearsAtScreening'] > 70
Requirement already satisfied: nhanes in /miniconda/lib/python3.12/site-packages (0.5.1)
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

Now let’s create a cleaned-up dataset that only includes the over70 variable along with the variable called HaveSeriousDifficultyHearing that denotes whether a person reports having serious hearing difficulty (coded as 1 for “yes” and 0 for “no”).

hearing_data = nhanes_data[['Over70', 'HaveSeriousDifficultyHearing']].dropna()
print(hearing_data)
          Over70  HaveSeriousDifficultyHearing
SEQN                                          
93703.0    False                           0.0
93704.0    False                           0.0
93705.0    False                           0.0
93706.0    False                           0.0
93707.0    False                           0.0
...          ...                           ...
102952.0   False                           0.0
102953.0   False                           0.0
102954.0   False                           0.0
102955.0   False                           0.0
102956.0   False                           0.0

[8365 rows x 2 columns]

First, what’s the probability of being over 70?

p_over_70 = hearing_data['Over70'].mean()
print(p_over_70)
0.10531978481769277

Second, what’s the probability of having hearing problems?

p_hearing_problem = hearing_data['HaveSeriousDifficultyHearing'].mean()
print(p_hearing_problem)
0.06276150627615062

What’s the probability for each combination of hearing problems/no problems and over 70/ not? We can create a table that finds the joint probability for each combination, using the pd.crosstab() function:

joint_table = pd.crosstab(hearing_data['Over70'], hearing_data['HaveSeriousDifficultyHearing'], normalize=True)
print(joint_table)
HaveSeriousDifficultyHearing       0.0       1.0
Over70                                          
False                         0.859653  0.035027
True                          0.077585  0.027735

Finally, what’s the probability of someone having hearing problems, given that they are over 70 years of age? To do this, we limit the computation of the probability of having hearing problems to only include those people who are over 70:

p_hearingproblem_given_over_70 = hearing_data.query('Over70 == True')['HaveSeriousDifficultyHearing'].mean()
print(p_hearingproblem_given_over_70)
0.2633371169125993

Now compute the opposite: What is the probability of being over 70 given that one has a hearing problem?

p_over_70_given_hearingproblem = hearing_data.query('HaveSeriousDifficultyHearing == True')['Over70'].mean()
print(p_over_70_given_hearingproblem)
0.4419047619047619