1Objectives¶
By the end of this lesson you will be able to:
Run and read a one-proportion and two-proportion
prop.test().Run and read a one-sample
t.test(~x, data=)and a two-samplet.test(y ~ g, data=).Run and read
BSDA’s summary-statistics tests,zsum.test()andtsum.test(), when a problem gives you , , and instead of raw data.Extract and interpret the pieces of an
htestobject: the test statistic, degrees of freedom, p-value, confidence interval, and point estimate.Explain why
prop.test()'s default confidence interval is not the same as the Wald interval taught by hand, and why that’s expected.
2From “how much does it vary” to “what can I conclude”¶
L09 showed you, by simulation, that a sample statistic bounces
around from sample to sample — and that the size of that bounce has a
formula, . Confidence intervals and
hypothesis tests are what you do with that fact: they turn “here’s one
sample’s statistic, and here’s how much it typically varies” into “here’s a
plausible range for the population value” (a CI) or “here’s how surprising
this sample would be if a specific claim were true” (a test). Every
function in this lesson returns the same kind of object — an htest — with
the same handful of pieces, once you know where to look. Reload the toolkit
and data if you’re starting fresh:
suppressMessages({library(mosaic); library(BSDA)})
survey <- read.csv("data/survey_sim.csv")
survey$class_year <- factor(survey$class_year,
levels = c("Freshman", "Sophomore", "Junior", "Senior"))3One-proportion inference: prop.test()¶
The sample proportion estimates an unknown population
proportion from successes in trials. L07 already
counted pet for us: 55 of 120 surveyed students are “Dog person.”
prop.test(x, n, p = ) tests whether the true rate could plausibly be some
claimed value — say, (a coin-flip split) — and returns a
confidence interval for either way:
prop.test(x = 55, n = 120, p = 0.5)
1-sample proportions test with continuity correction
data: 55 out of 120
X-squared = 0.675, df = 1, p-value = 0.4113
alternative hypothesis: true p is not equal to 0.5
95 percent confidence interval:
0.3678863 0.5514842
sample estimates:
p
0.4583333
Every htest object prints the same shape, and it’s worth being able to
name each piece: the test name (a 1-sample proportions test), data:
(what was tested), the test statistic (X-squared = 0.675, a
chi-square statistic here — later lessons use t or z), df
(degrees of freedom, 1), the p-value, a plain-language
alternative hypothesis sentence, the confidence interval, and the
sample estimate (). Read it as: 45.8% of this sample
are dog people; that’s not far enough from 50% to reject
(p-value 0.41, well above any usual 0.05 threshold), and the true rate is
plausibly anywhere from about 37% to 55%.
Every one of those pieces is also a named piece of the returned object — useful the moment you need one number without the whole printout, e.g. to report just a p-value in a sentence:
pt1 <- prop.test(x = 55, n = 120, p = 0.5)
pt1$statistic
pt1$parameter
pt1$p.value
pt1$conf.int
pt1$estimateX-squared
0.675
df
1
[1] 0.4113138
[1] 0.3678863 0.5514842
attr(,"conf.level")
[1] 0.95
p
0.4583333 Two small, honest details worth noticing: $statistic and $parameter
print with their names (X-squared, df) because they’re named
numbers, not bare ones — and $conf.int prints an extra attr(,"conf.level")
line, because R attaches the confidence level (0.95) as metadata on the
interval itself, not just in the printout above. Neither is an error;
that’s simply what a named/attributed R object looks like when auto-printed.
4Wald vs. Wilson: prop.test()'s CI is not the by-hand formula¶
Many intro textbooks (and calculators) teach a Wald confidence interval for a proportion by hand:
phat <- 55/120
zst <- qnorm(0.975)
phat - zst * sqrt(phat * (1 - phat) / 120)
phat + zst * sqrt(phat * (1 - phat) / 120)[1] 0.3691848
[1] 0.5474819That gives (0.3692, 0.5475) — close to, but not identical to,
prop.test()'s (0.3679, 0.5515) above. This is not a bug and not rounding
error: R’s prop.test() does not compute the Wald interval at all. By
default it computes a Wilson score interval with a continuity
correction — a different (and generally more accurate, especially for
small or near 0 or 1) method for the same job. Turning the
continuity correction off gets you closer, but still not to a plain Wald
interval, because the underlying method is still score-based, not Wald:
prop.test(x = 55, n = 120, p = 0.5, correct = FALSE)
1-sample proportions test without continuity correction
data: 55 out of 120
X-squared = 0.83333, df = 1, p-value = 0.3613
alternative hypothesis: true p is not equal to 0.5
95 percent confidence interval:
0.3718613 0.5473903
sample estimates:
p
0.4583333
5Two-proportion inference: prop.test() with two counts¶
prop.test(x = c(x1, x2), n = c(n1, n2)) compares two proportions directly.
L07’s two-way tally() already has the counts we need — the
rate of “Cat person” among Freshmen vs. Sophomores:
tally(pet ~ class_year, data = survey) class_year
pet Freshman Sophomore Junior Senior
Cat person 9 14 11 6
Dog person 16 11 16 12
Neither 5 11 6 39 of 30 Freshmen and 14 of 36 Sophomores are cat people:
prop.test(x = c(9, 14), n = c(30, 36))
2-sample test for equality of proportions with continuity correction
data: c out of c9 out of 3014 out of 36
X-squared = 0.24525, df = 1, p-value = 0.6204
alternative hypothesis: two.sided
95 percent confidence interval:
-0.3480262 0.1702485
sample estimates:
prop 1 prop 2
0.3000000 0.3888889
6One-sample and two-sample t-tests: t.test()¶
t.test() is mosaic’s masked, formula-aware version from
L05 — same function name as base R, now also accepting ~x, data= and y ~ g, data=. A one-sample test asks whether a population mean
could plausibly equal some claimed value, e.g. hours of
sleep:
t.test(~ sleep_hours, data = survey, mu = 7)
One Sample t-test
data: sleep_hours
t = -2.2997, df = 119, p-value = 0.02321
alternative hypothesis: true mean is not equal to 7
95 percent confidence interval:
6.60453 6.97047
sample estimates:
mean of x
6.7875
Same anatomy as prop.test(), different statistic: t = -2.30 (a t
statistic instead of chi-square), df = 119 (), p-value 0.023 —
below 0.05, so this sample’s mean (6.7875 hours) is far enough from 7 to
reject at the usual 5% level, and the 95% CI (6.60, 6.97)
does not contain 7, telling the same story.
A two-sample test compares two group means; the formula’s right side
takes the grouping variable. Restricting to two pet levels (t.test()
needs exactly two groups per call) compares sleep hours for cat people vs.
dog people:
sub <- subset(survey, pet != "Neither")
t.test(sleep_hours ~ pet, data = sub)
Welch Two Sample t-test
data: sleep_hours by pet
t = -0.3511, df = 85.958, p-value = 0.7264
alternative hypothesis: true difference in means between group Cat person and group Dog person is not equal to 0
95 percent confidence interval:
-0.5072222 0.3549495
sample estimates:
mean in group Cat person mean in group Dog person
6.687500 6.763636
A p-value of 0.73 and a CI comfortably straddling 0 both say the same
thing: no real evidence that cat people and dog people sleep differently in
this sample. Notice the title: “Welch Two Sample t-test” — R’s default
does not assume the two groups share the same variance (df = 85.958 is
a fractional, Welch-adjusted value, not the simpler you may see
in a hand-calculation). Add var.equal = TRUE if your course wants the
classic pooled-variance version to match a by-hand formula exactly — the
same “R’s smart default may not match the simplest hand formula” lesson as
prop.test()'s Wald-vs-Wilson point above.
7Summary-statistics tests: zsum.test() and tsum.test() (BSDA)¶
L05 already ran zsum.test() once — a one-sample z-test of
using only favstats()'s summary numbers, with a promise
that reading htest output in full was coming later. This is that lesson.
tsum.test() is zsum.test()'s -distribution sibling, for when
(the population SD) is not known and you only have ,
, and — the everyday case for real data. Pull the exact group
numbers from favstats():
favstats(sleep_hours ~ pet, data = sub) pet min Q1 median Q3 max mean sd n missing
1 Cat person 4.2 6.075 6.65 7.20 9.1 6.687500 1.026867 40 0
2 Dog person 3.9 6.050 6.80 7.55 8.8 6.763636 1.066035 55 0Feed those six numbers — no raw data, no data = argument at all — into
tsum.test():
tsum.test(mean.x = 6.687500, s.x = 1.026867, n.x = 40,
mean.y = 6.763636, s.y = 1.066035, n.y = 55)
Welch Modified Two-Sample t-Test
data: Summarized x and y
t = -0.3511, df = 85.958, p-value = 0.7264
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-0.5072222 0.3549495
sample estimates:
mean of x mean of y
6.687500 6.763636
t,df,p-value, and the confidence interval all match `t.test(sleep_hours- pet, data = sub)
above **exactly** — the raw-data version and the summary-statistics version are the same test, computed two different ways, just as [L05](./L05.md) showed for the one-sample z-test. Whenever a problem hands you $\bar{x}$, $s$, and $n$ instead of a data column,tsum.test()(two groups) orzsum.test()/one-sampletsum.test()` (one group, L05’s example) is the tool — never re-derive raw data that wasn’t given to you.
8Reading htest output: a quick reference¶
| Piece | Where it appears | What it means |
|---|---|---|
| Test name | First printed line | Which test ran — read it, don’t assume |
data: | Second line | What was tested (watch for the prop.test() two-vector quirk above) |
| Statistic | X-squared, t, or z | The standardized distance between data and |
df | Degrees of freedom | Not always — Welch’s t.test() uses a fractional value |
p-value | — | P(data this extreme or more, if were true) |
alternative hypothesis | A full sentence | Confirms exactly what’s being tested — read it every time |
confidence interval | A range | Plausible values for the population parameter |
sample estimates | One or two numbers | The actual , , or observed |
Every piece is also a named field on the saved object (result$statistic,
result$p.value, result$conf.int, ...) — save any test to a variable when
you need to pull out one number for a written answer, rather than
re-reading the printout by eye.
9Summary¶
Every test in this lesson returns an
htestobject with the same anatomy: test name, data, statistic, df (where applicable), p-value, alternative-hypothesis sentence, confidence interval, and sample estimate(s) — all also available as named fields ($statistic,$p.value,$conf.int, ...).prop.test(x, n, p=)(one proportion) andprop.test(c(x1,x2), c(n1,n2))(two proportions) test and interval-estimate population proportions.prop.test()'s default CI is a Wilson score interval with continuity correction, not the Wald interval taught by hand — close, but not numerically identical, and that’s expected, not an error.t.test(~x, data=)(one sample) andt.test(y ~ g, data=)(two samples, Welch by default) test and interval-estimate population means; addvar.equal = TRUEto match a classic pooled-variance hand formula.BSDA’szsum.test()andtsum.test()run the identical tests from summary statistics alone (, /, ) — the raw-data and summary-statistics versions of the same test agree exactly, so use whichever shape your problem actually gives you.L11 continues this thread with paired samples and chi-square tests for categorical data.