1Objectives¶
By the end of this lesson you will be able to:
Find a Normal-model probability (an area under the curve) with
xpnorm(), and read the picture it draws.Find a percentile/cutoff value with
xqnorm().Work with a simple discrete probability distribution (like
dbinom()for the binomial model).Run a small simulation with
do(n) *to see a long-run probability, instead of only computing it.
Everything below runs the same way on your own laptop or on the CSUB JupyterHub
(https://
2Setup¶
library(mosaic)
library(BSDA)31. xpnorm(): area under the Normal curve, with a picture¶
Your calculator’s normalcdf finds the area under a Normal curve between two
values. xpnorm() does the same job — and draws the curve with the area shaded in,
so you see the answer, not just compute it.
Suppose IQ scores follow a Normal model with mean 100 and standard deviation 15 (a standard textbook setup). What fraction of people score 115 or below?
xpnorm(115, mean = 100, sd = 15)
If X ~ N(100, 15), then
P(X <= 115) = P(Z <= 1) = 0.8413
P(X > 115) = P(Z > 1) = 0.1587
[1] 0.8413447What you’ll see: a bell curve for N(100, 15) with the region to the left of
115 shaded, a vertical line at 115 labeled z = 1, and a small unshaded region in
the right tail. The printed text gives you both halves for free — the area below
115 (0.8413) and the area above it (0.1587) — and the number returned, 0.8413447,
is the same value as P(X <= 115), just with more decimal places.
Try a value below the mean — the score 80:
xpnorm(80, mean = 100, sd = 15)
If X ~ N(100, 15), then
P(X <= 80) = P(Z <= -1.333) = 0.09121
P(X > 80) = P(Z > -1.333) = 0.9088
[1] 0.09121122About 9.1% of people score 80 or below — xpnorm() handles negative z-scores
exactly the same way, no special steps.
xpnorm() also accepts two values at once, splitting the curve into three
shaded regions — handy for a “between” question, like what fraction of people
score between 85 and 115?
xpnorm(c(85, 115), mean = 100, sd = 15)
If X ~ N(100, 15), then
P(X <= 85) = P(Z <= -1) = 0.1587 P(X <= 115) = P(Z <= 1) = 0.8413
P(X > 85) = P(Z > -1) = 0.8413 P(X > 115) = P(Z > 1) = 0.1587
[1] 0.1586553 0.8413447What you’ll see: the curve now shaded in three colors — a left tail below 85, a middle region between 85 and 115, and a right tail above 115, labeled with their probabilities (0.1587, 0.6827, 0.1587). That middle probability, 0.6827, should look familiar: it’s the “68” in the 68–95–99.7 rule, because 85 and 115 are exactly one SD below and above the mean of 100.
42. xqnorm(): going the other direction¶
xpnorm() starts with a value and finds a probability. xqnorm() (your
calculator’s invNorm) starts with a probability and finds the value — the
cutoff score for a given percentile.
What IQ score marks the 90th percentile (the score that beats 90% of people)?
xqnorm(0.90, mean = 100, sd = 15)
If X ~ N(100, 15), then
P(X <= 119.2233) = 0.9
P(X > 119.2233) = 0.1
[1] 119.2233What you’ll see: the same shaded-curve picture as xpnorm(), but now the
vertical line is drawn at the cutoff value (119.22) instead of at a value you
supplied — with 90% of the area shaded below it and 10% above. A score of about
119.2 sits right at the 90th percentile.
53. The binomial model: dbinom() and pbinom()¶
Not every random process is continuous like the Normal model. The binomial model counts successes in a fixed number of yes/no trials — like guessing on a 10-question true/false quiz, each guess independent, each with a 50% chance of being right.
dbinom(x, size, prob) gives the probability of exactly x successes.
What’s the probability of guessing exactly 7 out of 10 correct?
dbinom(7, size = 10, prob = 0.5)[1] 0.1171875About a 11.7% chance of exactly 7 correct. You can get the whole distribution at
once by feeding dbinom() a vector of every possible outcome, 0 through 10:
round(dbinom(0:10, size = 10, prob = 0.5), 4) [1] 0.0010 0.0098 0.0439 0.1172 0.2051 0.2461 0.2051 0.1172 0.0439 0.0098
[11] 0.0010Eleven numbers (for 0 through 10 correct), symmetric around the middle, peaking at 5 correct (24.6%) — exactly what you’d expect when guessing is a coin flip.
pbinom(x, size, prob) gives the cumulative probability — x or fewer
successes — matching your calculator’s binomcdf:
pbinom(6, size = 10, prob = 0.5)[1] 0.828125About an 82.8% chance of 6 or fewer correct. To flip that into “7 or more correct” (the upper tail), subtract from 1:
1 - pbinom(6, size = 10, prob = 0.5)[1] 0.17187564. Simulation: watching probability happen with do(n) *¶
Every probability above was computed with a formula. mosaic also lets you watch
probability play out, by repeating a random process many times and tallying the
results. rflip(10) flips a fair coin 10 times; do(1000) * repeats that entire
experiment 1000 times and stacks up the results into a data table:
set.seed(1209)
sims <- do(1000) * rflip(10)
head(sims) n heads tails prop
1 10 5 5 0.5
2 10 3 7 0.3
3 10 4 6 0.4
4 10 4 6 0.4
5 10 7 3 0.7
6 10 6 4 0.6set.seed(1209) makes the “random” simulation exactly reproducible — anyone who
runs this same code gets these same 1000 rows. Each row is one simulated set of 10
flips; heads counts how many came up heads. Tally up the heads column across
all 1000 simulated repetitions:
tally(~ heads, data = sims)heads
1 2 3 4 5 6 7 8 9
9 54 108 208 232 223 108 48 10 gf_histogram(~ heads, data = sims, binwidth = 1, fill = "#0072B2", color = "white",
xlab = "Number of heads in 10 flips",
ylab = "Number of simulated reps (of 1000)",
title = "Simulated distribution of heads in 10 coin flips")What you’ll see: a bell-shaped histogram, peaking at 5 heads, falling off
symmetrically toward 0 and 10 — the simulation rediscovers the same shape you
computed exactly with dbinom(0:10, size = 10, prob = 0.5) above, just from random
repetition instead of a formula.
Now check the simulation against the exact math from Section 3. What fraction of the 1000 simulated repetitions landed on 7 or more heads?
prop(~ heads >= 7, data = sims)prop_TRUE
0.166 The simulation says 16.6%; the exact binomial calculation, 1 - pbinom(6, 10, 0.5), said 17.2%. Close, but not identical — that gap is simulation noise,
and it would shrink if you simulated more than 1000 reps. This is the core idea
behind simulation-based statistics: random repetition approximates the exact
probability, and the more repetitions you run, the closer the approximation gets.
7Summary¶
xpnorm(q, mean=, sd=)finds the area under the Normal curve at or belowq, and draws it — the R match to your calculator’snormalcdf.xqnorm(p, mean=, sd=)finds the cutoff value for a given probabilityp— the match toinvNorm.dbinom(x, size=, prob=)gives the probability of exactlyxsuccesses;pbinom(x, size=, prob=)gives the probability ofxor fewer.do(n) * rflip(k)repeats ak-flip coin experimentntimes and stacks the results into a data table you cantally()or plot — alwaysset.seed()first so the “random” result is reproducible.Simulated probabilities approximate exact ones; the gap between them is simulation noise, not a mistake.
8Check your understanding¶
Adult male height is roughly Normal with mean 70 inches and SD 3 inches. Write the
xpnorm()call that finds the probability a random adult male is shorter than 65 inches.Using the same height model, write the
xqnorm()call for the height that marks the top 5% (the 95th percentile).A multiple-choice quiz has 8 questions, each with a 25% guessing chance (4 choices). Write the
dbinom()call for the probability of guessing exactly 3 correct, and thepbinom()call for the probability of 3 or fewer correct.In your own words, why did the simulated proportion in Section 4 (16.6%) not land on exactly the same number as the exact binomial calculation (17.2%)? What would you expect to happen to that gap if you changed
do(1000)todo(100000)?