In the last module, we reviewed statistical inference for one sample.
In this module, we will focus on tests for two samples.
In this lecture: two-sample dependent means (\mu_d)
So far in this module, we have focused on independent samples.
In this lecture, we shift to dependent (paired) samples.
The data is paired because we can link the observations.
You’re still the ZPD’s data analyst, but Deputy Chief Okonkwo has a different kind of question for you this time.
Before now, every question asked involved comparing different groups of recruits
Now, the questions are about the same recruits, measured twice.
Okonkwo wants to know whether things are changing:
R Setup| resident_name | exam_score_pre | exam_score_post | fitness_score_intake | fitness_score_6mo | response_time_before | response_time_after |
|---|---|---|---|---|---|---|
| Piper Ravensmoor | 73 | 80 | 54 | 51 | 9.2 | 8.0 |
| Rufus Copperfield | 61 | 70 | 85 | 87 | 12.1 | 11.7 |
| Willa Grimsby | 72 | 74 | 67 | 70 | 6.0 | 5.3 |
If we run independent_means() on either the “before” column or the “after” column, we are ignoring the pairing.
Because the same recruit is measured twice, their two scores are correlated.
Pairing lets us focus on within-subject change.
d_i = y_{i1} - y_{i2}
All of our inference is now built on this single column of differences, not the original columns.
\bar{d} \pm t_{\alpha/2, n-1} \frac{s_d}{\sqrt{n}}
\bar{d} is the mean of the differences, s_d is the standard deviation of the differences, and n is the number of pairs (not the number of raw observations).
t has n-1 degrees of freedom (df).
Hypotheses
Two-Tailed
H_0: \mu_d = \mu_0
H_1: \mu_d \ne \mu_0
Left-Tailed
H_0: \mu_d \ge \mu_0
H_1: \mu_d < \mu_0
Right-Tailed
H_0: \mu_d \le \mu_0
H_1: \mu_d > \mu_0
\mu_d is the population mean of the differences,
\mu_0 is the hypothesized value of that mean difference (often 0, for “no change”).
Test Statistic:
t_0 = \frac{\bar{d}-\mu_0}{{\dfrac{s_d}{\sqrt{n}}}} \sim t_{n-1}
R)We will use the dependent_means() function from library(ssstats) to perform statistical inference.
Generic syntax:
dataset_name |> dependent_means(
col1 = first_measurement,
col2 = second_measurement,
alternative = "two" | "less" | "greater",
mu = hypothesized_difference,
alpha = alpha_level
)dependent_means().
col1: the first paired measurement.
col2: the second paired measurement.
alternative: the direction of the test; default is two.
mu: the hypothesized mean difference under H_0; default is 0.
alpha: the significance level; default is 0.05.
R will subtract col1 - col2.Okonkwo calls you in: “We started pulling recruits with low written-exam scores into a short remedial coaching session before their retake. I want proof this is worth the department’s time – did coaching actually raise their scores?”
We will use the zootopia_paired dataset to answer the following question:
We’ll work with exam_score_pre and exam_score_post for the same recruits.
Paired (dependent) means
Complete pairs: 30
Point estimate: x̅[exam_score_post] − x̅[exam_score_pre] = 4.8333
SD of differences: 1.9667
95% CI for μ[exam_score_post] − μ[exam_score_pre]: (4.099, 5.5677)
Hypotheses:
H₀: μ[exam_score_post] − μ[exam_score_pre] = 0
H₁: μ[exam_score_post] − μ[exam_score_pre] ≠ 0
Test statistic: t(29) = 13.461
p-value: < 0.001
Conclusion: Reject the null hypothesis (p = < 0.001 < α = 0.050)
Did recruits’ exam scores improve after coaching?
How do we translate this into hypotheses?
exam_score_post - exam_score_pre.Hypotheses:
For the dependent_means() function, we will set
mu = 0alternative = "greater".zootopia_paired |> dependent_means(col1 = exam_score_post,
col2 = exam_score_pre,
mu = 0,
alternative = "greater")Paired (dependent) means
Complete pairs: 30
Point estimate: x̅[exam_score_post] − x̅[exam_score_pre] = 4.8333
SD of differences: 1.9667
95% CI for μ[exam_score_post] − μ[exam_score_pre]: (4.099, 5.5677)
Hypotheses:
H₀: μ[exam_score_post] − μ[exam_score_pre] ≤ 0
H₁: μ[exam_score_post] − μ[exam_score_pre] > 0
Test statistic: t(29) = 13.461
p-value: < 0.001
Conclusion: Reject the null hypothesis (p = < 0.001 < α = 0.050)
Hypotheses
Test Statistic and p-Value
Rejection Region
Conclusion and Interpretation
Okonkwo again: “Recruits go through a fitness assessment when they start, and we test them again at the 6-month mark. Command wants to know – overall, is fitness actually changing over those six months, or are we just imagining a trend?”
We will use the zootopia_paired dataset to answer the following question:
We’ll work with fitness_score_intake and fitness_score_6mo.
Paired (dependent) means
Complete pairs: 30
Point estimate: x̅[fitness_score_6mo] − x̅[fitness_score_intake] = 0.5333
SD of differences: 4.1749
95% CI for μ[fitness_score_6mo] − μ[fitness_score_intake]: (-1.0256, 2.0923)
Hypotheses:
H₀: μ[fitness_score_6mo] − μ[fitness_score_intake] = 0
H₁: μ[fitness_score_6mo] − μ[fitness_score_intake] ≠ 0
Test statistic: t(29) = 0.7
p-value: 0.490
Conclusion: Fail to reject the null hypothesis (p = 0.490 ≥ α = 0.050)
Does recruit fitness change between intake and the 6-month mark?
How do we translate this into hypotheses?
Hypotheses:
For the dependent_means() function, we will set
mu = 0alternative = "two".zootopia_paired |> dependent_means(col1 = fitness_score_6mo,
col2 = fitness_score_intake,
mu = 0,
alternative = "two")Paired (dependent) means
Complete pairs: 30
Point estimate: x̅[fitness_score_6mo] − x̅[fitness_score_intake] = 0.5333
SD of differences: 4.1749
95% CI for μ[fitness_score_6mo] − μ[fitness_score_intake]: (-1.0256, 2.0923)
Hypotheses:
H₀: μ[fitness_score_6mo] − μ[fitness_score_intake] = 0
H₁: μ[fitness_score_6mo] − μ[fitness_score_intake] ≠ 0
Test statistic: t(29) = 0.7
p-value: 0.490
Conclusion: Fail to reject the null hypothesis (p = 0.490 ≥ α = 0.050)
Hypotheses
Test Statistic and p-Value
Rejection Region
Conclusion and Interpretation
d_1, d_2, \ldots, d_n \sim N(\mu_d, \sigma_d^2)
Notice this assumption is about d, the differences, not about col1 and col2 individually.
We will use a quantile-quantile (Q-Q) plot to check this, plus a histogram of the differences.
R)dependent_qq() function from library(ssstats) to assess normality.Just like the independent-samples case, the CI for a median difference is built from ranks.
Instead of pairwise differences between two groups, we now work with averages of pairs of differences within the same set of d_i’s.
\dfrac{d_i + d_j}{2}
The median of these averages is the Hodges-Lehmann estimate of the median difference.
The CI is then found by ranking the Walsh averages and selecting upper and lower bounds.
The differences are ranked based on the absolute value of the difference.
Then, ranks can be identified as “positive” or “negative” based on the original direction of the difference.
| X | Y | D | |D| | Rank |
|---|---|---|---|---|
| 5 | 8 | -3 | 3 | - 1.5 |
| 8 | 5 | 3 | 3 | + 1.5 |
| 4 | 4 | 0 | 0 | ——— |
Hypotheses
Two-Tailed
H_0: M_d = M_0
H_1: M_d \ne M_0
Left-Tailed
H_0: M_d \ge M_0
H_1: M_d < M_0
Right-Tailed
H_0: M_d \le M_0
H_1: M_d > M_0
M_d is the population median of the differences,
M_0 is the hypothesized median difference (often 0).
Test Statistic
T_0 = \begin{cases} R_+ = \text{sum of positive ranks} & \text{if left-tailed} \\ R_- = \text{sum of negative ranks} & \text{if right-tailed} \\ \min(R_+, R_-) & \text{if two-tailed} \end{cases}
R)We will use the dependent_medians() function from library(ssstats) to perform statistical inference.
Generic syntax:
dataset_name |> dependent_medians(
col1 = first_measurement,
col2 = second_measurement,
alternative = "two" | "less" | "greater",
m = hypothesized_difference,
alpha = alpha_level
)dependent_medians().
col1: the first paired measurement.
col2: the second paired measurement. The function calculates col1 - col2, so order matters.
alternative: the direction of the test; default is two.
m: the hypothesized median difference under H_0; default is 0.
alpha: the significance level; default is 0.05.
Recall the research question:
Hypotheses:
For the dependent_medians() function, we will set
mu = 0alternative = "greater".zootopia_paired |> dependent_medians(col1 = exam_score_post,
col2 = exam_score_pre,
alternative = "greater")Paired (dependent) medians
Complete pairs: 30
Effective pairs (non-zero differences): 30
M[exam_score_post] = 74
M[exam_score_pre] = 69.5
Hodges-Lehmann estimate of median difference: 5
95% CI for M[exam_score_post] − M[exam_score_pre]: (4, 5.5)
Hypotheses:
H₀: M[exam_score_post] − M[exam_score_pre] ≤ 0
H₁: M[exam_score_post] − M[exam_score_pre] > 0
Test statistic: T = 465
p-value: < 0.001
Conclusion: Reject the null hypothesis (p = < 0.001 < α = 0.050)
Hypotheses
Test Statistic and p-Value
Rejection Region
Conclusion and Interpretation
Recall: the fitness score differences looked questionable on the Q-Q plot – some recruits improved, some plateaued, some backslid.
How do we translate the question into hypotheses this time?
For the dependent_medians() function, we will set
m = 0alternative = "two".Recall the research question:
Paired (dependent) medians
Complete pairs: 30
Effective pairs (non-zero differences): 28
M[fitness_score_6mo] = 70
M[fitness_score_intake] = 71
Hodges-Lehmann estimate of median difference: 1
95% CI for M[fitness_score_6mo] − M[fitness_score_intake]: (-1, 2.5)
Hypotheses:
H₀: M[fitness_score_6mo] − M[fitness_score_intake] = 0
H₁: M[fitness_score_6mo] − M[fitness_score_intake] ≠ 0
Test statistic: T = 272
p-value: 0.406
Conclusion: Fail to reject the null hypothesis (p = 0.406 ≥ α = 0.050)
Hypotheses
Test Statistic and p-Value
Rejection Region
Conclusion and Interpretation
Dependent (paired) data comes from the same subject measured twice.
The analysis you choose should match the shape of the differences:
If the differences meet normality (dependent_means()):
If the differences do not meet normality (dependent_medians()):