This is not a fill-in-the-blanks sheet. All the code is here and all of it runs.
We assume you can already open RStudio, knit an .Rmd,
read a data file, and index a data frame. If any of that is shaky, the
two cheat sheets in this folder cover it, and it is a reasonable thing
to ask an AI assistant to walk you through. What follows is the part
that is specific to this course.
Everything below uses one seed, so your numbers will match the printed ones:
set.seed(67)
Every standard distribution in R comes with four functions, distinguished by their first letter. Learn the pattern once and you know all of them.
| Prefix | Gives you | Normal | Reads as |
|---|---|---|---|
d |
density \(f(x)\) | dnorm(x) |
height of the curve at x |
p |
cdf \(F(x) = P(X \le x)\) | pnorm(q) |
area to the left of
q |
q |
quantile \(F^{-1}(p)\) | qnorm(p) |
the value with area p to its left |
r |
random draws | rnorm(n) |
n simulated observations |
Note: p and q are inverses of each
other.
pnorm(1.96) # area to the left of 1.96
## [1] 0.9750021
qnorm(0.975) # the value with 0.975 to its left
## [1] 1.959964
The distributions you will need this term, with their R names:
| Distribution | R name | Parameters |
|---|---|---|
| Normal | norm |
mean, sd: the
standard deviation, not the variance |
| Exponential | exp |
rate |
| Chi-square | chisq |
df |
| Student \(t\) | t |
df |
| Fisher \(F\) | f |
df1, df2 |
| Uniform | unif |
min, max |
| Binomial | binom |
size, prob |
Two examples of the kind of thing you will do all term:
qt(0.975, df = 23) # two-sided 5% critical value for a t with 23 df
## [1] 2.068658
1 - pf(4.2, df1 = 2, df2 = 40) # p-value of an observed F of 4.2
## [1] 0.02209493
Be careful:
rnorm(n, mean, sd)takes the standard deviation. To sample from \(N(10, 4)\), whose variance is 4, you writernorm(n, 10, 2).
The whole idea of a sampling distribution is: the statistic
is a random variable, so compute it many times and look at the spread of
the answers. replicate is how you do that.
replicate(5, mean(rnorm(20, 10, 2))) # five separate experiments
## [1] 9.644336 10.072767 9.526072 9.942828 10.039465
Each entry is the mean of its own fresh sample of 20. They differ because the sample differs, and that variation corresponds to the sampling distribution.
Three other functions worth knowing:
set.seed(67)
sample(1:10, size = 4) # draw without replacement
## [1] 4 1 6 7
sample(c("a","b"), 6, replace = TRUE) # with replacement
## [1] "a" "a" "b" "a" "a" "b"
round(c(mean = mean(rnorm(100)), sd = sd(rnorm(100))), 3)
## mean sd
## -0.049 0.998
set.seed makes randomness reproducible. Set it once at
the top of every analysis.
Every ggplot is the same three pieces: data, an
aesthetic mapping (aes, which says which
variable goes on which axis), and one or more geoms
added with +.
d <- data.frame(z = rnorm(500))
ggplot(d, aes(x = z)) + geom_histogram(bins = 30)
Comparing a histogram with a theoretical density only works if both are on the same vertical scale. Counts are not; densities are. This idiom appears in all four questions below:
ggplot(d, aes(x = z)) +
geom_histogram(aes(y = after_stat(density)), bins = 30,
fill = "grey80", colour = "white") +
stat_function(fun = dnorm, args = list(mean = 0, sd = 1),
colour = "#B3261E", linewidth = 0.8) +
labs(x = "z", y = "density")
after_stat(density) rescales the bars so their total
area is 1; stat_function draws any function of
x, here the \(N(0,1)\)
density.
To compare the same plot under different settings, such as different sample sizes, stack all the simulated values into one data frame, with a column saying which setting each value belongs to. Then facet_wrap() draws one panel per setting, side by side. This lets you watch a distribution change as \(n\) grows, which is exactly what the central limit theorem describes.
dd <- rbind(data.frame(n = "n = 1", m = replicate(2000, mean(rexp(1)))),
data.frame(n = "n = 30", m = replicate(2000, mean(rexp(30)))))
ggplot(dd, aes(m)) +
geom_histogram(bins = 30, fill = "grey80", colour = "white") +
facet_wrap(~ n, scales = "free") + labs(x = expression(bar(X)), y = "count")
A histogram shows normality loosely. A QQ plot is a bit more precise. Points on the line means the sample matches the theoretical quantiles.
ggplot(d, aes(sample = z)) + stat_qq(size = 0.6) + stat_qq_line(colour = "#B3261E") +
labs(x = "theoretical quantiles", y = "sample quantiles")
And the plot this whole course is about:
xx <- runif(60, 0, 10); yy <- 3 + 2 * xx + rnorm(60, 0, 2)
ggplot(data.frame(xx, yy), aes(xx, yy)) +
geom_point(size = 0.9) +
geom_smooth(method = "lm", se = FALSE, colour = "#1F5FA9", linewidth = 0.7) +
labs(x = "x", y = "y")
Useful:
labs()for axis titles,facet_wrap()for panels,theme_minimal()for a clean look,expression(bar(X))for maths in a label.
Each question states a mathematical result and shows code that tests it. The results are Weeks 2 to 6 of this course, so you are seeing here the pictures before the proofs.
Let \(X_1,\dots,X_n\) be i.i.d. \(N(\mu,\sigma^2)\). Then exactly \[\bar X \sim N\!\left(\mu,\ \frac{\sigma^2}{n}\right).\]
Take \(\mu = 10\), \(\sigma^2 = 4\), \(n = 20\):
mu <- 10; sigma <- 2; n <- 20
means <- replicate(5000, mean(rnorm(n, mu, sigma)))
c(simulated_mean = mean(means), theoretical_mean = mu,
simulated_sd = sd(means), theoretical_sd = sigma / sqrt(n))
## simulated_mean theoretical_mean simulated_sd theoretical_sd
## 10.0046918 10.0000000 0.4522440 0.4472136
ggplot(data.frame(means), aes(means)) +
geom_histogram(aes(y = after_stat(density)), bins = 40,
fill = "grey80", colour = "white") +
stat_function(fun = dnorm, args = list(mean = mu, sd = sigma / sqrt(n)),
colour = "#B3261E", linewidth = 0.8) +
labs(x = expression(bar(X)), y = "density")
To discuss.
Question 1 was exact because the population was normal. The CLT says \(\bar X\) is approximately normal for large \(n\) whatever the population, provided the variance is finite.
The exponential with rate 1 is strongly right-skewed, which makes it a hard test:
sizes <- c(1, 5, 30)
clt <- do.call(rbind, lapply(sizes, function(k)
data.frame(n = factor(paste("n =", k), levels = paste("n =", sizes)),
m = replicate(5000, mean(rexp(k, rate = 1))))))
ggplot(clt, aes(m)) +
geom_histogram(aes(y = after_stat(density)), bins = 40,
fill = "grey80", colour = "white") +
facet_wrap(~ n, scales = "free") +
labs(x = expression(bar(X)), y = "density")
ggplot(subset(clt, n == "n = 30"), aes(sample = m)) +
stat_qq(size = 0.5) + stat_qq_line(colour = "#B3261E") +
labs(title = "n = 30", x = "theoretical", y = "sample")
To discuss.
Let \(X_1,\dots,X_k\) be independent \(N(0,1)\) and set \(Y_k=\sum_{i=1}^k X_i^2\). Then \(Y_k\sim\chi^2_k\), with mean \(k\) and variance \(2k\). Since \(Y_k\) is itself a sum of independent terms, the CLT applies to it: \[Z_k=\frac{Y_k-k}{\sqrt{2k}}\ \longrightarrow\ N(0,1).\]
ks <- c(1, 5, 50)
chi <- do.call(rbind, lapply(ks, function(k) {
Y <- replicate(5000, sum(rnorm(k)^2))
data.frame(k = factor(paste("k =", k), levels = paste("k =", ks)),
z = (Y - k) / sqrt(2 * k)) }))
ggplot(chi, aes(z)) +
geom_histogram(aes(y = after_stat(density)), bins = 40,
fill = "grey80", colour = "white") +
stat_function(fun = dnorm, colour = "#B3261E", linewidth = 0.7) +
facet_wrap(~ k) + coord_cartesian(xlim = c(-3, 4)) +
labs(x = expression(Z[k]), y = "density")
To discuss.
This course is, in particular, concerned with the study of one random variable: the estimated slope. You can watch it behave before deriving anything.
Generate from a known model, fit it, and repeat:
beta0 <- 100; beta1 <- 20; sigma <- 5; n <- 25
x <- seq(1, 10, length.out = n)
one_slope <- function() {
y <- beta0 + beta1 * x + rnorm(n, mean = 0, sd = sigma)
coef(lm(y ~ x))[2]
}
slopes <- replicate(2000, one_slope())
Sxx <- sum((x - mean(x))^2)
c(mean_slope = mean(slopes), true_beta1 = beta1,
sd_slope = sd(slopes), theoretical = sigma / sqrt(Sxx))
## mean_slope true_beta1 sd_slope theoretical
## 20.0054222 20.0000000 0.3733863 0.3698001
ggplot(data.frame(slopes), aes(slopes)) +
geom_histogram(aes(y = after_stat(density)), bins = 40,
fill = "grey80", colour = "white") +
stat_function(fun = dnorm, args = list(mean = beta1, sd = sigma / sqrt(Sxx)),
colour = "#B3261E", linewidth = 0.8) +
labs(x = expression(hat(beta)[1]), y = "density")
To discuss.
x, beta1 and sigma never
change between runs. So why is one_slope() different every
time?