Section 1 of 12

1 Before you start

Before you begin, take a few minutes to check what you already know and how confident you feel. You will see the same questions again at the end of the module — this helps both you and us measure what you have learned. Click an option for every question and confidence rating, then click Next to continue.

Pre-test

You set alpha = 0.05 and your test returns p = 0.02. What does alpha represent here?

Pre-test

A regulator rejects a drug's null hypothesis of no effect, but in truth the drug does nothing. Which error is this?

Pre-test

A trial is designed with 80% power to detect a clinically important effect. What does this mean?

Pre-test

An underpowered trial of 8 patients returns a non-significant p-value for a drug that truly works. What most likely happened?

Pre-test

You want the n per group for 80% power to detect Cohen's d of 0.5 at alpha 0.05. Which call solves for it?

Pre-test

You decide to switch to a one-sided test only after seeing the effect points the way you hoped. Why is this a problem?

Pre-test

With 10,000 patients, a mean HbA1c difference of 0.02% reaches p < 0.001. How should you report it?

Pre-test

You compare a continuous, roughly Normal outcome across THREE treatment arms at once. Which test fits?

Pre-confidence

I can explain alpha, Type I and Type II error, and power in plain clinical words, and say why an underpowered study can miss a real effect.

Not at all confident
Fully confident
Pre-confidence

I can plan a study's sample size with pwr.t.test(), commit to a one-sided or two-sided test before seeing the data, and tell statistical significance from clinical significance.

Not at all confident
Fully confident
Pre-confidence

I can recognise whether data are paired or independent, choose and run the correct base-R test after checking its assumptions, and tidy the result with broom::tidy().

Not at all confident
Fully confident
Section 2 of 12

2 Introduction

In Part I you learned to state a null and an alternative, run a test, and read the p-value it returns without the classic misreadings. A p-value alone does not tell you what to do next. This part gives you the rule for acting on it and an honest account of how that rule can fail: the two errors every test can make, the power to catch a real effect, and the choice of which test actually fits your data.

This part of the module covers four foundations, each building toward a defensible decision:

  • Errors and power — alpha, Type I and Type II error, and why an underpowered study misses real effects.
  • Planning sample size — fixing three of effect size, sample size, alpha, and power, and letting pwr solve for the fourth.
  • Significance, two ways — one-sided versus two-sided tests, and statistical versus clinical significance.
  • Choosing a test — a decision aid for t.test, aov, wilcox.test, chisq.test and cor.test, the paired-data trap, and checking assumptions.

By the end of this part you will be able to explain alpha, Type I and Type II error, and power in clinical words, plan a sample size with pwr.t.test(), commit to a one-sided or two-sided test honestly, tell statistical from clinical significance, recognise when data are PAIRED rather than independent, and choose and run the correct base-R test, tidying its result with broom::tidy().

Try every snippet in the R Scratchpad on the right. This part needs no data file — you will build small trials with c(), matrix() and set.seed() and let base R run the tests. Use the native pipe |> if you reach for a pipe, and call library() explicitly for every package.

Section 3 of 12

3 Alpha, the two errors, and power

Once you understand the p-value, you need a rule for acting on it, and an honest account of how that rule can fail. Every test can be wrong in two directions, and planning for them happens before you collect a single patient.

You fix a threshold called alpha — the significance level — before seeing the data, conventionally 0.05. If the p-value falls below alpha you reject H0 and call the result statistically significant. Alpha is the risk you are willing to take of a false alarm.

The learner walks away understanding that α is a false-alarm threshold fixed before data, that p < α is the rule for declaring significance, and that the rule can fail in two ways — a false alarm (Type I) or a missed effect (Type II).
The learner walks away understanding that α is a false-alarm threshold fixed before data, that p < α is the rule for declaring significance, and that the rule can fail in two ways — a false alarm (Type I) or a missed effect (Type II).

That false alarm is a Type I error: rejecting H0 when it is actually true — declaring an effect that is not there. Set alpha to 0.05 and you accept a 5% chance of this when the null holds. The opposite mistake is a Type II error: failing to reject H0 when there really is an effect — missing a drug that genuinely works.

A hypothesis test has four possible outcomes, and the two errors are mirror images — Type I raises a false alarm when nothing is there, Type II misses a real effect that is.
A hypothesis test has four possible outcomes, and the two errors are mirror images — Type I raises a false alarm when nothing is there, Type II misses a real effect that is.

The chance of a Type II error is called beta. Power is 1 - beta: the probability that your study detects a real effect of a given size. A study with 80% power has a 1-in-5 chance of missing a true effect. Power rises with the sample size, the effect size, and a looser alpha.

Power is the share of the real-effect curve that sits past the significance line, so anything that separates the real effect from the noise (a larger sample, a bigger effect, or a looser alpha) raises power and shrinks beta, the chance of missing a true effect.
Power is the share of the real-effect curve that sits past the significance line, so anything that separates the real effect from the noise (a larger sample, a bigger effect, or a looser alpha) raises power and shrinks beta, the chance of missing a true effect.

Here is the clinical danger. An underpowered study — too few patients — will miss real effects and return non-significant p-values even when the treatment works. A non-significant result from a tiny trial tells you almost nothing. This is why you plan sample size in advance.

Section 3.1 of 12

3.1 Planning sample size with pwr

You can compute the sample size a study needs before running it. The pwr package ties together four quantities — effect size, sample size, alpha, and power. Give it any three and it solves for the fourth. For comparing two means, use pwr.t.test().

Suppose you want 80% power to detect a medium effect (Cohen's d of 0.5) at alpha 0.05, with equal-sized groups. Leave n out and pwr returns the n per group you need. Read the n in its printout.

Try it out

Try this snippet in the R Scratchpad on the right.

Try this snippet
library(pwr)
pwr.t.test(d = 0.5, sig.level = 0.05, power = 0.80, type = "two.sample")
The learner walks away understanding that sample size is not guessed but computed, by fixing effect size, alpha, and power and letting pwr.t.test() solve for the one quantity you left blank.
The learner walks away understanding that sample size is not guessed but computed, by fixing effect size, alpha, and power and letting pwr.t.test() solve for the one quantity you left blank.

The novice habit to avoid: running the study first and computing power afterwards from the result you got. So-called post-hoc power adds nothing — it is just a rescaling of the p-value. Power analysis belongs at the planning stage, with an effect size you decide is clinically worth detecting.

Section 4 of 12

4 One-sided vs two-sided, and statistical vs clinical significance

With alpha and power in hand, two final decisions shape how you report a test honestly: which direction you test in, and whether a significant result actually matters to a patient.

A two-sided test asks whether the groups differ at all — in either direction. A one-sided test asks only whether one group is greater than the other. A one-sided test has more power to detect an effect in the chosen direction, but it is blind to a difference the other way.

A one-sided test spends all of alpha in a single tail, which lowers the cutoff and buys more power in that direction, at the price of being unable to detect a real effect the other way.
A one-sided test spends all of alpha in a single tail, which lowers the cutoff and buys more power in that direction, at the price of being unable to detect a real effect the other way.

The rule that keeps you honest: commit to one-sided or two-sided BEFORE you see the data, and use two-sided as the safe default. Choosing one-sided after peeking — because the effect happened to point the way you hoped — quietly doubles your real Type I error. That is a form of cheating, even when unintentional.

In R the direction is the alternative argument to t.test(). The default is "two.sided"; you would write alternative = "less" only if you had pre-registered a one-directional hypothesis.

Choosing your test direction after peeking at the data secretly puts your error budget in both tails, doubling the real false-positive rate from 5% to 10%, which is why you commit before looking and default to two-sided.
Choosing your test direction after peeking at the data secretly puts your error budget in both tails, doubling the real false-positive rate from 5% to 10%, which is why you commit before looking and default to two-sided.
Section 4.1 of 12

4.1 Statistical significance is not clinical significance

A result can be statistically significant — p below alpha — yet clinically meaningless. With ten thousand patients, a mean HbA1c difference of 0.02% can reach p < 0.001 while changing no treatment decision. Significance answers 'is it detectable?', not 'does it matter?'.

So report the effect, not just the verdict. Always report an effect estimate WITH a confidence interval in clinical units, not a bare p-value. 'HbA1c fell by 0.8% (95% CI 0.5 to 1.1)' tells a clinician how much and how precisely. 'p = 0.002' tells them almost nothing they can act on.

A significant p-value only means an effect was detectable, so judge whether it matters by reading the effect estimate and its confidence interval in clinical units.
A significant p-value only means an effect was detectable, so judge whether it matters by reading the effect estimate and its confidence interval in clinical units.
Section 5 of 12

5 Choosing and running the right test

Everything so far has used a t-test, but the right test depends on your data: how many groups, what kind of outcome, and crucially whether the observations are paired. This section is your decision aid.

Match the question to the test by the shape of your data:

  • t.test — compare a mean against a value (one-sample), or two group means (two-sample), or before-vs-after on the same patients (PAIRED).
  • aov — compare the means of THREE or more groups at once (analysis of variance).
  • wilcox.test / kruskal.test — the non-parametric alternatives when the outcome is skewed or ordinal, for two groups and for 3+ groups respectively.
  • chisq.test / fisher.test / prop.test — for categorical data: an association in a table, or a comparison of proportions (fisher.test for small counts).
  • cor.test — test whether two continuous measurements are correlated.
The right statistical test is not a default like the t-test but a consequence of three properties of your data, how many groups you compare, whether the outcome is numeric, skewed, or categorical, and crucially whether the observations are paired.
The right statistical test is not a default like the t-test but a consequence of three properties of your data, how many groups you compare, whether the outcome is numeric, skewed, or categorical, and crucially whether the observations are paired.

Each returns a tidy summary. Wrap any result in broom::tidy() to get a one-row tibble of the estimate, statistic, p-value, and CI — ideal for putting in a report or a table.

Try it out

Try this snippet in the R Scratchpad on the right.

Try this snippet
library(broom)
drug <- c(6.8, 7.1, 6.5, 7.4, 6.9)
placebo <- c(7.6, 8.0, 7.4, 7.9, 8.2)
tidy(t.test(drug, placebo))
broom::tidy() converts a model's verbose, irregular console printout into a single neat row of standard columns (estimate, statistic, p.value, CI) that you can drop straight into a report table.
broom::tidy() converts a model's verbose, irregular console printout into a single neat row of standard columns (estimate, statistic, p.value, CI) that you can drop straight into a report table.

When the outcome is a category rather than a measurement, the test changes shape. Build a 2x2 of treatment arm against outcome and ask chisq.test() whether the two are associated.

Try it out

Try this snippet in the R Scratchpad on the right.

Try this snippet
tbl <- matrix(c(18, 12, 7, 23), nrow = 2, byrow = TRUE,
              dimnames = list(Arm = c("Drug", "Placebo"),
                              Outcome = c("Improved", "Not")))
tbl
chisq.test(tbl)
The chi-squared test scores how far a treatment trial's observed counts sit from what independence would predict, and a clear diagonal of gaps means the arm and the outcome are associated.
The chi-squared test scores how far a treatment trial's observed counts sit from what independence would predict, and a clear diagonal of gaps means the arm and the outcome are associated.
Section 5.1 of 12

5.1 Paired data is the trap that catches everyone

Two measurements are paired when they come from the same patient — a baseline and a follow-up, or a left eye and a right eye. They are linked, so they are not independent. Data are independent instead when each value comes from a different patient, as in two separate treatment arms.

A learner walks away understanding that two measurements are paired when they come from the same patient and are therefore linked rather than independent, whereas independent measurements come from different patients with nothing tying them together.
A learner walks away understanding that two measurements are paired when they come from the same patient and are therefore linked rather than independent, whereas independent measurements come from different patients with nothing tying them together.

Here is the single most common test-selection error: running an independent-samples test on paired data. For before-vs-after on the same patients, you must pass paired = TRUE to t.test(). A paired test compares each patient to themselves, removing between-patient variation, so it is far more powerful — and ignoring the pairing gives a wrong p-value.

Before-and-after measurements on the same people are paired, so linking each patient to themself removes between-patient noise and makes the paired t-test far more powerful than wrongly treating the two time points as independent groups.
Before-and-after measurements on the same people are paired, so linking each patient to themself removes between-patient noise and makes the paired t-test far more powerful than wrongly treating the two time points as independent groups.

Watch for the same structure under other names: repeated measures over time, and clustered data such as several samples from one patient or several patients from one ward. Whenever observations share a source, they are not independent, and a plain two-sample test is wrong.

Try it out

Try this snippet in the R Scratchpad on the right.

Try this snippet
baseline <- c(8.1, 7.8, 9.0, 8.4, 7.9)
followup <- c(7.2, 7.0, 8.1, 7.5, 7.1)
t.test(baseline, followup, paired = TRUE)
When observations share a source they are not independent, so pairing within the source removes the between-unit spread that would otherwise swamp a plain two-sample test.
When observations share a source they are not independent, so pairing within the source removes the between-unit spread that would otherwise swamp a plain two-sample test.
Section 5.2 of 12

5.2 Check the assumptions first

A t-test and ANOVA assume the outcome is roughly Normal and the observations are independent. Running a t-test on a skewed or ordinal outcome without checking can mislead you — switch to wilcox.test() when the data are clearly non-Normal.

When an outcome is clearly skewed, the mean a t-test relies on gets pulled into the tail, so comparing ranks with wilcox.test() gives a more trustworthy answer.
When an outcome is clearly skewed, the mean a t-test relies on gets pulled into the tail, so comparing ranks with wilcox.test() gives a more trustworthy answer.

Check approximate Normality two ways. A QQ plot plots your data against what a Normal distribution would predict; points near the straight line mean roughly Normal. The Shapiro-Wilk test (shapiro.test()) gives a formal p-value, where a small p flags non-Normality. Use the plot as your main guide; the test alone over-flags in large samples.

Draw a QQ plot for a small sample of lab values. A base-R plot appears as soon as you call the plotting function — no printing needed.

Try it out

Try this snippet in the R Scratchpad on the right.

Try this snippet
hba1c <- c(7.2, 8.1, 6.5, 9.4, 7.0, 8.8, 6.9, 7.6)
qqnorm(hba1c)
qqline(hba1c)
A QQ plot is the primary, visual check for Normality, points hugging the reference line mean roughly Normal, and Shapiro-Wilk's p-value only confirms that read rather than overruling it, because in large samples the test flags trivial, harmless departures.
A QQ plot is the primary, visual check for Normality, points hugging the reference line mean roughly Normal, and Shapiro-Wilk's p-value only confirms that read rather than overruling it, because in large samples the test flags trivial, harmless departures.

When the QQ plot bends away from the line, switch to the non-parametric wilcox.test() — it compares ranks, not means, so a skewed outcome cannot distort it.

Try it out

Try this snippet in the R Scratchpad on the right.

Try this snippet
drug <- c(6.8, 7.1, 6.5, 7.4, 6.9)
placebo <- c(7.6, 8.0, 7.4, 7.9, 8.2)
wilcox.test(drug, placebo)
The Wilcoxon test replaces each measurement with its position in the sorted list, so only the order matters and a skewed or extreme value cannot distort the comparison.
The Wilcoxon test replaces each measurement with its position in the sorted list, so only the order matters and a skewed or extreme value cannot distort the comparison.
Section 6 of 12

6 Put it together

This Parsons problem gives you the right lines in the wrong order, plus a few lines that do not belong. Drag the correct lines into order and leave the wrong ones in the bank.

Parsons problem · Run a paired test and tidy the result

All the lines you need are in the Line bank on the left — some may be distractors you should leave behind. Drag the lines you need into the Your solution column on the right, in the correct order, then click Check.

Task: Switch on broom, store each patient's baseline and follow-up HbA1c, run a PAIRED t-test because the readings come from the same patients, then tidy it into a one-row table.

Line bank
  • followup <- c(7.2, 7.0, 8.1, 7.5, 7.1)
  • baseline <- c(8.1, 7.8, 9.0, 8.4, 7.9)
  • tidy(t.test(baseline, followup, paired = FALSE))
  • library(paired)
  • tidy(chisq.test(baseline, followup))
  • library(broom)
  • tidy(t.test(baseline, followup, paired = TRUE))
Your solution
  • Drop lines here, in order.

Now you will make the call that trips up most beginners: spotting which comparison in a trial is PAIRED and which is INDEPENDENT, then running each with the right test and reporting the effect in clinical units. The worked example fades its support — study the full solution, then fill the gap, then solve a fresh one.

Worked example · Paired vs independent in one small trial

Work through this example in three stages. You unlock each stage only after the tutor confirms the previous one. Each stage removes more of the scaffolding — by the end you are writing it yourself.

Problem: Five patients on a new drug have HbA1c measured at baseline and after 12 weeks. The baseline-vs-followup comparison is WITHIN the same patients, so it is paired: use a paired t-test. Run it, then report the mean drop in HbA1c (clinical units).

Stage 1 · Study the solved example
Fully solved solution
baseline <- c(8.1, 7.8, 9.0, 8.4, 7.9)
followup <- c(7.2, 7.0, 8.1, 7.5, 7.1)
t.test(baseline, followup, paired = TRUE)
round(mean(baseline) - mean(followup), 2)
Walk-through
  1. The two readings come from the SAME patients, so the comparison is paired
  2. Pass paired = TRUE to t.test so it compares each patient to themselves
  3. Report the effect in clinical units: the mean fall in HbA1c, here mean(baseline) - mean(followup)
The learner walks away able to look at any two columns of trial data and decide, before writing a line of R, whether the comparison is within the same units (paired) or between different groups (independent), and to report the result as a difference in clinical units.
The learner walks away able to look at any two columns of trial data and decide, before writing a line of R, whether the comparison is within the same units (paired) or between different groups (independent), and to report the result as a difference in clinical units.
Section 7 of 12

7 Check your understanding

You have reached the end of the module. Try the same questions again — your answers here, paired with your pre-test answers, are how we measure what the module taught you. Answer every question and confidence rating, then click Submit and see results to view your score.

Post-test

You set alpha = 0.05 and your test returns p = 0.02. What does alpha represent here?

Post-test

A regulator rejects a drug's null hypothesis of no effect, but in truth the drug does nothing. Which error is this?

Post-test

A trial is designed with 80% power to detect a clinically important effect. What does this mean?

Post-test

An underpowered trial of 8 patients returns a non-significant p-value for a drug that truly works. What most likely happened?

Post-test

You want the n per group for 80% power to detect Cohen's d of 0.5 at alpha 0.05. Which call solves for it?

Post-test

You decide to switch to a one-sided test only after seeing the effect points the way you hoped. Why is this a problem?

Post-test

With 10,000 patients, a mean HbA1c difference of 0.02% reaches p < 0.001. How should you report it?

Post-test

You compare a continuous, roughly Normal outcome across THREE treatment arms at once. Which test fits?

Post-confidence

I can explain alpha, Type I and Type II error, and power in plain clinical words, and say why an underpowered study can miss a real effect.

Not at all confident
Fully confident
Post-confidence

I can plan a study's sample size with pwr.t.test(), commit to a one-sided or two-sided test before seeing the data, and tell statistical significance from clinical significance.

Not at all confident
Fully confident
Post-confidence

I can recognise whether data are paired or independent, choose and run the correct base-R test after checking its assumptions, and tidy the result with broom::tidy().

Not at all confident
Fully confident
Section 8 of 12

8 Your results

Here is how your post-test answers compare with your pre-test answers. The pre/post pairing is the most reliable way to see what this module actually taught you.

Your score

Submit the post-test to see your results.

Muddiest point

What is the one thing from this module that is still unclear to you?

Rate this module

Overall, how would you rate this module?

How likely are you to recommend this module to a peer? (0 = not at all, 10 = extremely likely)