<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Bayesian analysis of the Curtis Flowers trials
Copyright 2020 Allen B. Downey
License
Step1:  On September 5, 2020, prosecutors in Mississippi dropped charges against Curtis Flowers, freeing him after 23 years of incarceration.
Flowers had been tried six times for a 1996 multiple murder.  Two trials ended in a mistrial due to a hung jury; four trials ended in convictions.  
According to this NPR report
After each conviction, a higher court struck down the initial ruling. The latest ruling invalidating Flowers' conviction, and death sentence, came from the U.S. Supreme Court in June of last year. The justices noted the Mississippi Supreme Court had found that in three prior convictions the prosecution had misrepresented evidence and deliberately eliminated Black jurors.
Since the racial composition of the juries was the noted reason the last conviction was invalidated, the purpose of this article is to explore the relationship between the composition of the juries and the outcome of the trials.
Flowers' trials were the subject of the In the Dark podcast, which reported the racial composition of the juries and the outcomes
Step2:  To prepare for the updates, I'll form a joint distribution of the two probabilities.
Step3:  Here's how we compute the update.
Assuming that a guilty verdict must be unanimous, the probability of conviction is
$ p = p_1^{n_1} ~ p_2^{n_2}$
where
$p_1$ is the probability a white juror votes to convict
$p_2$ is the probability a black juror votes to convict
$n_1$ is the number of white jurors
$n_2$ is the number of black jurors
The probability of an acquittal or hung jury is the complement of $p$.
The following function performs a Bayesian update given the composition of the jury and the outcome, either 'guilty' or 'hung'.  We could also do an update for an acquittal, but since that didn't happen, I didn't implement it.
Step4:  I'll use the following function to plot the marginal posterior distributions after each update.
Step5:  Here's the update for the first trial.
Step6:  Since there were no black jurors for the first trial, we learn nothing about their probability of conviction, so the posterior distribution is the same as the prior.
The posterior distribution for white voters reflects the data that 12 of them voted to convict.
Here are the posterior distributions after the second trial.
Step7:  And the third.
Step8:  Since the first three verdicts were guilty, we infer that all 36 jurors voted to convict, so the estimated probabilities for both groups are high.
The fourth trials ended in a mistrial due to a hung jury, which implies that at least one juror refused to vote to convict.  That decreases the estimated probabilities for both juror pools, but it has a bigger effect on the estimate for black jurors because the total prior data pertaining to black jurors is less, so the same amount of new data moves the needle more.
Step9:  The effect of the fifth trial is similar; it decreases the estimates for both pools, but the effect on the estimate for black jurors is greater.
Step10:  Finally, here are the posterior distributions after all six trials.
Step11:  The posterior distributions for the two pools are substantially different.  Here are the posterior means.
Step12:  Based on the outcomes of all six trials, we estimate that the probability is 98% that a white juror would vote to convict, and the probability is 68% that a black juror would vote to convict.
Again, those results are based on the modeling simplifications that
All six juries saw essentially the same evidence,
The probabilities we're estimating did not change over the period of the trials, and
Interactions between jurors did not have substantial effects on their votes.
Prediction
Now we can use the joint posterior distribution to estimate the probability of conviction as a function of the composition of the jury.
I'll draw a sample from the joint posterior distribution.
Step13:  Here's the probability that white jurors were more likely to convict.
Step14:  The following function takes this sample and a hypothetical composition and returns the posterior predictive distribution for the probability of conviction.
Step15:  According to Wikipedia
Step16:  And with 6 white and 6 black jurors.
Step17:  With a jury that represents the population of Montgomery County, the probability Flowers would be convicted is 14-15%.
However, notice that the credible intervals for these estimates are quite wide.  Based on the data, the actual probabilities could be in the range from near 0 to 50%.
The following figure shows the probability of conviction as a function of the number of black jurors.
The probability of conviction is highest with an all-white jury, and drops quickly if there are a few black jurors.  After that, the addition of more black jurors has a relatively small effect.
These results suggest that all-white juries have a substantially higher probability of convicting a defendant, compared to a jury with even a few non-white jurors.
Step18:  Double Check
Let's compute the results a different way to double check.
For the four guilty verdicts, we don't need to make or update the joint distribution; we can update the distributions for the two pools separately.
Step19:  We can use the posteriors from those updates as priors and update them based on the two trials that resulted in a hung jury.
Step20:  The posterior marginals look the same.
Step21:  And yield the same posterior means.
Step22:  Here's the probability that a fair jury would convict four times out of six.
<ASSISTANT_TASK:>
Python Code:
# If we're running on Colab, install empiricaldist
# https://pypi.org/project/empiricaldist/
import sys
IN_COLAB = 'google.colab' in sys.modules
if IN_COLAB:
    !pip install empiricaldist
# Get utils.py
import os
if not os.path.exists('utils.py'):
    !wget https://github.com/AllenDowney/ThinkBayes2/raw/master/code/soln/utils.py
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from empiricaldist import Pmf
from utils import decorate, savefig
Explanation: Bayesian analysis of the Curtis Flowers trials
Copyright 2020 Allen B. Downey
License: Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
End of explanation
ps = np.linspace(0, 1, 101)
prior_p1 = Pmf(1.0, ps)
prior_p1.index.name = 'p1'
prior_p2 = Pmf(1.0, ps)
prior_p2.index.name = 'p2'
Explanation: On September 5, 2020, prosecutors in Mississippi dropped charges against Curtis Flowers, freeing him after 23 years of incarceration.
Flowers had been tried six times for a 1996 multiple murder.  Two trials ended in a mistrial due to a hung jury; four trials ended in convictions.  
According to this NPR report
After each conviction, a higher court struck down the initial ruling. The latest ruling invalidating Flowers' conviction, and death sentence, came from the U.S. Supreme Court in June of last year. The justices noted the Mississippi Supreme Court had found that in three prior convictions the prosecution had misrepresented evidence and deliberately eliminated Black jurors.
Since the racial composition of the juries was the noted reason the last conviction was invalidated, the purpose of this article is to explore the relationship between the composition of the juries and the outcome of the trials.
Flowers' trials were the subject of the In the Dark podcast, which reported the racial composition of the juries and the outcomes:
Trial         Jury                     Outcome
  1           All white                Guilty
  2           11 white, 1 black        Guilty
  3           11 white, 1 black        Guilty
  4           7 white, 5 black         Hung jury
  5           9 white, 3 black         Hung jury
  6           11 white, 1 black        Guilty
We can use this data to estimate the probability that white and black jurors would vote to convict, and then use those estimates to compute the probability of a guilty verdict.
As a modeling simplification, I'll assume:
The six juries were presented with essentially the same evidence, prosecution case, and defense;
The probabilities of conviction did not change over the years of the trials (from 1997 to 2010); and
Each juror votes independently of the others; that is, I ignore interactions between jurors.
I'll use the same prior distribution for white and black jurors, a uniform distribution from 0 to 1.
End of explanation
from utils import make_joint
joint = make_joint(prior_p2, prior_p1)
prior_pmf = Pmf(joint.stack())
prior_pmf.head()
Explanation: To prepare for the updates, I'll form a joint distribution of the two probabilities.
End of explanation
def update(prior, data):
    n1, n2, outcome = data
    likelihood = prior.copy()
    for p1, p2 in prior.index:
        like = p1**n1 * p2**n2
        if outcome == 'guilty':
            likelihood.loc[p1, p2] = like
        elif outcome == 'hung':
            likelihood.loc[p1, p2] = 1-like
        else:
            raise ValueError()
            
    posterior = prior * likelihood
    posterior.normalize()
    return posterior
Explanation: Here's how we compute the update.
Assuming that a guilty verdict must be unanimous, the probability of conviction is
$ p = p_1^{n_1} ~ p_2^{n_2}$
where
$p_1$ is the probability a white juror votes to convict
$p_2$ is the probability a black juror votes to convict
$n_1$ is the number of white jurors
$n_2$ is the number of black jurors
The probability of an acquittal or hung jury is the complement of $p$.
The following function performs a Bayesian update given the composition of the jury and the outcome, either 'guilty' or 'hung'.  We could also do an update for an acquittal, but since that didn't happen, I didn't implement it.
End of explanation
from utils import pmf_marginal
def plot_marginals(posterior):
    marginal0 = pmf_marginal(posterior, 0)
    marginal0.plot(label='white')
    
    marginal1 = pmf_marginal(posterior, 1)
    marginal1.plot(label='black')
    decorate(xlabel='Probability of voting to convict',
             ylabel='PDF',
             title='Marginal posterior distributions')
Explanation: I'll use the following function to plot the marginal posterior distributions after each update.
End of explanation
data1 = 12, 0, 'guilty'
posterior1 = update(prior_pmf, data1)
plot_marginals(posterior1)
Explanation: Here's the update for the first trial.
End of explanation
data2 = 11, 1, 'guilty'
posterior2 = update(posterior1, data2)
plot_marginals(posterior2)
Explanation: Since there were no black jurors for the first trial, we learn nothing about their probability of conviction, so the posterior distribution is the same as the prior.
The posterior distribution for white voters reflects the data that 12 of them voted to convict.
Here are the posterior distributions after the second trial.
End of explanation
data3 = 11, 1, 'guilty'
posterior3 = update(posterior2, data3)
plot_marginals(posterior3)
Explanation: And the third.
End of explanation
data4 = 7, 5, 'hung'
posterior4 = update(posterior3, data4)
plot_marginals(posterior4)
Explanation: Since the first three verdicts were guilty, we infer that all 36 jurors voted to convict, so the estimated probabilities for both groups are high.
The fourth trials ended in a mistrial due to a hung jury, which implies that at least one juror refused to vote to convict.  That decreases the estimated probabilities for both juror pools, but it has a bigger effect on the estimate for black jurors because the total prior data pertaining to black jurors is less, so the same amount of new data moves the needle more.
End of explanation
data5 = 9, 3, 'hung'
posterior5 = update(posterior4, data5)
plot_marginals(posterior5)
Explanation: The effect of the fifth trial is similar; it decreases the estimates for both pools, but the effect on the estimate for black jurors is greater.
End of explanation
data6 = 11, 1, 'guilty'
posterior6 = update(posterior5, data6)
plot_marginals(posterior6)
Explanation: Finally, here are the posterior distributions after all six trials.
End of explanation
marginal_p1 = pmf_marginal(posterior6, 0)
marginal_p2 = pmf_marginal(posterior6, 1)
marginal_p1.mean(), marginal_p2.mean(), 
Explanation: The posterior distributions for the two pools are substantially different.  Here are the posterior means.
End of explanation
sample = posterior6.sample(1000)
Explanation: Based on the outcomes of all six trials, we estimate that the probability is 98% that a white juror would vote to convict, and the probability is 68% that a black juror would vote to convict.
Again, those results are based on the modeling simplifications that
All six juries saw essentially the same evidence,
The probabilities we're estimating did not change over the period of the trials, and
Interactions between jurors did not have substantial effects on their votes.
Prediction
Now we can use the joint posterior distribution to estimate the probability of conviction as a function of the composition of the jury.
I'll draw a sample from the joint posterior distribution.
End of explanation
np.mean([p1 > p2 for p1, p2 in sample])
Explanation: Here's the probability that white jurors were more likely to convict.
End of explanation
def prob_guilty(sample, n1, n2):
    ps = [p1**n1 * p2**n2 for p1, p2 in sample]
    return Pmf.from_seq(ps)
Explanation: The following function takes this sample and a hypothetical composition and returns the posterior predictive distribution for the probability of conviction.
End of explanation
pmf = prob_guilty(sample, 7, 5)
pmf.mean(), pmf.credible_interval(0.9)
Explanation: According to Wikipedia:
As of the 2010 United States Census, there were 10,925 people living in the county. 53.0% were White, 45.5% Black or African American, 0.4% Asian, 0.1% Native American, 0.5% of some other race and 0.5% of two or more races. 0.9% were Hispanic or Latino (of any race).
A jury drawn at random from the population of Montgomery County would be expected to have 5 or 6 black jurors.
Here's the probability of conviction with a panel of 7 white and 5 black jurors.
End of explanation
pmf = prob_guilty(sample, 6, 6)
pmf.mean(), pmf.credible_interval(0.9)
Explanation: And with 6 white and 6 black jurors.
End of explanation
pmf_seq = []
n2s = range(0, 13)
for n2 in n2s:
    n1 = 12 - n2
    pmf = prob_guilty(sample, n1, n2)
    pmf_seq.append(pmf)
means = [pmf.mean() for pmf in pmf_seq]
lows = [pmf.quantile(0.05) for pmf in pmf_seq]
highs = [pmf.quantile(0.95) for pmf in pmf_seq]
means
plt.plot(n2s, means)
plt.fill_between(n2s, lows, highs, color='C0', alpha=0.1)
decorate(xlabel='Number of black jurors',
         ylabel='Probability of a guilty verdict',
         title='Probability of a guilty verdict vs jury composition',
         ylim=[0, 1])
Explanation: With a jury that represents the population of Montgomery County, the probability Flowers would be convicted is 14-15%.
However, notice that the credible intervals for these estimates are quite wide.  Based on the data, the actual probabilities could be in the range from near 0 to 50%.
The following figure shows the probability of conviction as a function of the number of black jurors.
The probability of conviction is highest with an all-white jury, and drops quickly if there are a few black jurors.  After that, the addition of more black jurors has a relatively small effect.
These results suggest that all-white juries have a substantially higher probability of convicting a defendant, compared to a jury with even a few non-white jurors.
End of explanation
from scipy.stats import binom
k1 = 12 + 11 + 11 + 11
like1 = binom(k1, ps).pmf(k1)
prior_p1 = Pmf(like1, ps)
k2 = 0 + 1 + 1 + 1
like2 = binom(k2, ps).pmf(k2)
prior_p2 = Pmf(like2, ps)
prior_p1.plot()
prior_p2.plot()
Explanation: Double Check
Let's compute the results a different way to double check.
For the four guilty verdicts, we don't need to make or update the joint distribution; we can update the distributions for the two pools separately.
End of explanation
prior = Pmf(make_joint(prior_p2, prior_p1).stack())
posterior = update(prior, data4)
posterior = update(posterior, data5)
Explanation: We can use the posteriors from those updates as priors and update them based on the two trials that resulted in a hung jury.
End of explanation
plot_marginals(posterior)
Explanation: The posterior marginals look the same.
End of explanation
marginal_p1 = pmf_marginal(posterior, 0)
marginal_p2 = pmf_marginal(posterior, 1)
marginal_p1.mean(), marginal_p2.mean(), 
Explanation: And yield the same posterior means.
End of explanation
binom.pmf(4, 6, 0.15)
Explanation: Here's the probability that a fair jury would convict four times out of six.
End of explanation
<END_TASK>