Skip to main content

Section D.2 Difference in Means

Before we test whether men are more variable than women, let’s warm up by confirming that men are taller than women, on average. We’ll use bootstrap resampling to estimate the sampling distribution of the difference in means. The following is a utility function that computes the difference between the first two elements of a sequence.
Listing D.2.1. Python Code
def diff(seq):
    """Difference between the first two elements of a sequence.

    seq: sequence

    returns: float
    """
    return np.diff(seq)[0]
We’ll use it to compute the difference in means in a sample, which is the “test statistic”.
Listing D.2.2. Python Code
def diff_means(sample):
    """Difference in average height (M minus F).

    sample: DataFrame with _SEX and HTM4 columns

    returns: float
    """
    grouped_heights = sample.groupby("_SEX")["HTM4"]
    return -diff(grouped_heights.mean())
The difference is defined so a positive value indicates that men are taller. Here’s an example using the bootstrapped sample.
Listing D.2.3. Python Code
$ diff_means(sample)
14.455796580284954
Men are about 14 cm taller than women, on average.
The following function takes a DataFrame and a function that computes a test statistic. It runs resample many times, computes the test statistic for each sample, and returns a list of test statistics.
Listing D.2.4. Python Code
def sampling_dist(df, test_stat, iters=201):
    """Generate bootstrap samples and compute test statistic.

    df: DataFrame
    test_stat: function that takes a DataFrame
    iters: number of samples

    returns: list of float
    """
    return [test_stat(resample(df)) for i in range(iters)]
Here’s how we call it. The result is a sample from the sampling distribution of differences in means.
Listing D.2.5. Python Code
$ t1 = sampling_dist(brfss, diff_means)
np.mean(t1)
14.433755828000592
The following function uses KDE to estimate the density of the sampling distribution, uses the estimated density to compute a confidence interval, and generates a plot that shows the sampling distribution, the mean, and the 95% CI.
Listing D.2.6. Python Code
from scipy.stats import gaussian_kde
from empiricaldist import Pmf


def plot_sampling_distribution(data, format_str=".2f", **options):
    """Plot the sampling distribution, mean and CI."""
    m, s = np.mean(data), np.std(data)
    qs = np.linspace(m - 4 * s, m + 4 * s, 501)
    ps = gaussian_kde(data)(qs)
    pmf = Pmf(ps, qs)
    pmf.normalize()
    low, high = pmf.make_cdf().inverse([0.025, 0.975])
    pmf.plot(**options)
Here are the results for the sampling distribution of the difference in means.
Listing D.2.7. Python Code
plot_sampling_distribution(t1)
plt.title("Difference in means (cm)", fontsize=14)
The difference in means is about 14.4 cm. If we simulate the data collection process and compute the difference in means many times, it varies a little, but it is never close to zero.
The following function estimates the probability that a value from this distribution exceeds 0, which is the p-value for the hypothesis that men are taller than women on average.
Listing D.2.8. Python Code
from scipy.stats import norm


def p_value(t):
    m, s = np.mean(t), np.std(t)
    if m > 0:
        return norm.cdf(0, m, s)
    else:
        return norm.sf(0, m, s)
Listing D.2.9. Python Code
$ p_value(t1)
0.0
The p-value is so close to zero we can’t compute it with floating-point arithmetic, which means it is truly negligible.
This result means that if we collect another sample this size from the same population, it is practically impossible that the women in the sample would be taller, on average.