Fundamentals · Guiding Questions

The Box Model Part 3 - Modelling Using a Normal Distribution

Keep the Interface Page Open in Another Tab /Fundamentals/box-model-part-3/

This page is about turning a box model into a probability. Work through the tasks with the interactive page open beside you.

Coding Task 1

Implementing Task 2 in R

The steps we follow in the Box Model Playground are easy to do in R yourself. Doing so is the best way to see that the visualisation is not doing anything mysterious. You'll need the tidyverse loaded, as we will be using ggplot2:

library(tidyverse)
set.seed(1)   # so your numbers match the ones printed below

Step 1 — build the box and take one sample

The box holds one '1' ticket (a head) and one '0' ticket (a tail). Drawing 100 times with replacement is the same as flipping 100 coins.

box <- c(1, 0)

one_sample <- sample(box, size = 100, replace = TRUE)
head(one_sample, 20)
sum(one_sample)
 [1] 1 0 1 1 0 1 1 1 0 0 1 1 1 1 1 0 0 0 0 1
[1] 49

So that particular set of 100 flips gave 49 heads. A single sample tells us very little on its own — which is exactly why the next step repeats it.

Step 2 — repeat it, and check the shape

This is the Central Limit Theorem section in code. replicate() is the equivalent of hammering the + Repeat 100 button: here we build 10,000 samples and keep the sum of each one.

sums <- replicate(10000, sum(sample(box, size = 100, replace = TRUE)))
head(sums)
[1] 53 44 55 55 52 46
ggplot(tibble(sums), aes(x = sums)) +
  geom_histogram(binwidth = 1, fill = "grey80", colour = "white") +
  labs(title = "Sums of 100 coin flips, repeated 10,000 times",
       x = "Sum of the sample", y = "Count") +
  theme_minimal()
A ggplot histogram titled 'Sums of 100 coin flips, repeated 10,000 times'. Grey bars form a bell shape peaking near a sum of 50 at a count of about 790, spanning roughly 34 to 65.
Figure 9 — the same bell shape the Central Limit Theorem section builds up.

Step 3 — calculate the EV and SE

For a sum of n draws: EV = n × (average ticket), and SE = √n × (SD of the tickets).

n <- 100

ev <- n * mean(box)
ev

sd_box <- sqrt(mean((box - mean(box))^2))   # population SD -- see the warning below
sd_box

se <- sqrt(n) * sd_box
se
[1] 50
[1] 0.5
[1] 5
Watch out

Do not use sd(box) here. R's sd() divides by n−1, because it is estimating a population SD from a sample. The box is not a sample — it is the whole population, and we know it exactly. For our two tickets:

> sd(box)
[1] 0.7071068

That is 0.707 instead of 0.5, which would give SE = 7.07 instead of 5 — a completely different answer. Hence the longhand sqrt(mean((box - mean(box))^2)).

Worth a sanity check: the simulated sums should have roughly this mean and spread.

mean(sums)
sd(sums)
[1] 50.055
[1] 5.019611

Close to 50 and 5, as promised. (Here sd() is the right function — sums genuinely is a sample.)

Step 4 — overlay the normal curve

This is the Modelling Using a Normal Distribution section in code.

ggplot(tibble(sums), aes(x = sums)) +
  geom_histogram(aes(y = after_stat(density)),
                 binwidth = 1, fill = "grey80", colour = "white") +
  stat_function(fun = dnorm, args = list(mean = ev, sd = se),
                colour = "red", linewidth = 1) +
  labs(title = "Simulated sums with the fitted normal curve",
       x = "Sum of the sample", y = "Density") +
  theme_minimal()
The same histogram rescaled to density, with a red normal curve for mean 50 and standard deviation 5 drawn over it. The curve follows the tops of the bars closely.
Figure 10 — the same red curve the Modelling section draws, from your own code.
Note after_stat(density) rescales the histogram so its total area is 1. Without it, the bars are counts in the thousands and the curve is invisible along the bottom of the plot.

Step 5 — read off the probabilities

This is the Finding Probabilities section in code. pnorm() gives the area under a normal curve to the left of a value. For [70, ∞) we want the area to the right, so pass lower.tail = FALSE:

pnorm(70, mean = ev, sd = se, lower.tail = FALSE)
[1] 3.167124e-05

For the interval [50, 70], subtract the area below 50 from the area below 70:

pnorm(70, mean = ev, sd = se) - pnorm(50, mean = ev, sd = se)
[1] 0.4999683

Both match what the playground displayed in Task 2 — 3e-05, and about 0.5. The interactive page is running this same calculation for you.

Bonus: how well does the simulation agree with the curve?

You can also estimate the probability straight from the 10,000 simulated sums, without the normal curve at all:

mean(sums >= 70)
[1] 0

Zero — not because it is impossible, but because a 0.003% event is not expected to turn up in only 10,000 tries. This is precisely why we model with the normal curve rather than simulating: the curve still gives sensible answers far out in the tails, where simulation runs out of data.

Extension Task 1

Rolling a Dice (Part 2)

Remember your brother from before? Well, next week, you and your brother are in the same predicament. One ice cream left — who gets it? Your brother proposes a new game. You roll a 6-sided die 50 times and take the sum, just as you did last time. If the sum is between 145 and 175 (inclusive), you get the ice cream. Otherwise, your brother gets it.

What is the probability that you get the ice cream? No step-by-step this time — you have already done every part of this in Task 3.

Show the answer

About 0.49, so slightly under half. The box is unchanged from Task 3 (tickets 1,2,3,4,5,6, 50 draws, sum), giving EV = 175 and SE ≈ 12.08. This time set the Lower Boundary to 145 and the Upper Boundary to 175, with neither ∞ checkbox ticked.

In R:

box <- c(1, 2, 3, 4, 5, 6)
n   <- 50
ev  <- n * mean(box)
se  <- sqrt(n) * sqrt(mean((box - mean(box))^2))

pnorm(175, mean = ev, sd = se) - pnorm(145, mean = ev, sd = se)
[1] 0.4935085

Notice the asymmetry that works in his favour. The upper boundary is exactly the expected value, so the interval captures only the bottom half of the distribution, and 145 is far enough below the centre that it cuts off very little. Your brother has learned from last week.