\(z = \dfrac{M - \mu}{\sigma_M}\)
\(\renewcommand{\CancelColor}{\red}z = \dfrac{M - \mu}{\require{enclose}\enclose{horizontalstrike}{\sigma_M}}\)
\(t = \dfrac{M-\mu}{s_M}\)
\[z = \dfrac{M - \mu}{\require{enclose}\enclose{horizontalstrike}{\sigma_M}} \ \ \ \ \ \ \ \ \ \ \ \ \ t = \dfrac{M - \mu}{s_M}\]
\[ \begin{align} \text{Standard error} = \sigma_M = \dfrac{\sigma}{\sqrt{n}} \ \text{or...} \ \dfrac{\sqrt{\sigma^2}}{\sqrt{n}} \ \text{or...} \ \sqrt{\dfrac{\sigma^2}{n}} \\ \\ \text{Estimated standard error} = s_M = \dfrac{s}{\sqrt{n}} \ \text{or...} \ \dfrac{\sqrt{s^2}}{\sqrt{n}} \ \text{or...} \ \sqrt{\dfrac{s^2}{n}} \end{align} \]
\(\text{Population variance} = \sigma^2 = \dfrac{SS}{N}\)
\(\text{Sample variance} = s^2 = \dfrac{SS}{df} = \dfrac{SS}{n-1}\)
\(\text{Sample standard deviation} = s = \sqrt{\dfrac{SS}{df}} = \sqrt{\dfrac{SS}{n-1}}\)
data = {
var values = jStat(-4, 4, 210)[0],
<!-- df = df, -->
arr = [];
for (var i in values) {
arr.push(
{
value: values[i],
density: jStat.studentt.pdf(values[i], df)
}
)
}
return arr;
}
norm_data = {
var values = jStat(-4, 4, 210)[0],
<!-- df = df, -->
arr = [];
for (var i in values) {
arr.push(
{
value: values[i],
density: jStat.normal.pdf(values[i], 0, 1)
}
)
}
return arr;
}
<!-- norm_data -->
chart = {
const svg = d3.select(DOM.svg(width, height));
<!-- svg.append("g") -->
<!-- .call(xAxis); -->
<!-- svg.append("g") -->
<!-- .call(yAxis); -->
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "red")
.attr("stroke-width", 4)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("d", line);
svg.append("path")
.datum(norm_arr)
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", 2)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke-dasharray", "5, 5")
.attr("d", line)
.attr("class", "invertable");
return svg.node();
}
<!-- margin = ({top: 20, right: 0, bottom: 30, left: 40}) -->
margin = ({top: 20, right: 0, bottom: 0, left: 0})
line = d3.line()
.x(d => x(d.value))
.y(d => y(d.density))
x = d3.scaleLinear()
.domain([d3.min(data, d => d.value * 0.9), d3.max(data, d => d.value * 0.9)]).nice()
.range([margin.left, width - margin.right])
<!-- y = d3.scaleLinear() -->
<!-- .domain([d3.min(data, d => d.density * 0.9), d3.max(data, d => d.density / 0.9)]) -->
<!-- .range([height - margin.bottom, margin.top]) -->
y = d3.scaleLinear()
.domain([0, 0.4])
.range([height - margin.bottom, margin.top])Normal distribution \(t\) distribution
Proportion in 1 tail |
0.1 |
0.05 |
0.025 |
0.01 |
0.005 |
|---|---|---|---|---|---|
| Proportion in 2 tails |
0.2 | 0.1 | 0.05 | 0.02 | 0.01 |
| 1 | 3.078 | 6.314 | 12.706 | 31.821 | 63.657 |
| 2 | 1.886 | 2.920 | 4.303 | 6.965 | 9.925 |
| 3 | 1.638 | 2.353 | 3.182 | 4.541 | 5.841 |
| 4 | 1.533 | 2.132 | 2.776 | 3.747 | 4.604 |
| 5 | 1.476 | 2.015 | 2.571 | 3.365 | 4.032 |
| 6 | 1.440 | 1.943 | 2.447 | 3.143 | 3.707 |
| 7 | 1.415 | 1.895 | 2.365 | 2.998 | 3.499 |
| \(df\) 8 | 1.397 | 1.860 | 2.306 | 2.896 | 3.355 |
| 9 | 1.383 | 1.833 | 2.262 | 2.821 | 3.250 |
| 10 | 1.372 | 1.812 | 2.228 | 2.764 | 3.169 |
| 11 | 1.363 | 1.796 | 2.201 | 2.718 | 3.106 |
| 12 | 1.356 | 1.782 | 2.179 | 2.681 | 3.055 |
| 13 | 1.350 | 1.771 | 2.160 | 2.650 | 3.012 |
| 14 | 1.345 | 1.761 | 2.145 | 2.624 | 2.977 |
| 15 | 1.341 | 1.753 | 2.131 | 2.602 | 2.947 |
| ... | ... | ... | ... | ... | ... |
Proportion in 1 tail |
0.1 |
0.05 |
0.025 |
0.01 |
0.005 |
|---|---|---|---|---|---|
| Proportion in 2 tails |
0.2 | 0.1 | 0.05 | 0.02 | 0.01 |
| 1 | 3.078 | 6.314 | 12.706 | 31.821 | 63.657 |
| 2 | 1.886 | 2.920 | 4.303 | 6.965 | 9.925 |
| 3 | 1.638 | 2.353 | 3.182 | 4.541 | 5.841 |
| 4 | 1.533 | 2.132 | 2.776 | 3.747 | 4.604 |
| 5 | 1.476 | 2.015 | 2.571 | 3.365 | 4.032 |
| 6 | 1.440 | 1.943 | 2.447 | 3.143 | 3.707 |
| 7 | 1.415 | 1.895 | 2.365 | 2.998 | 3.499 |
| \(df\) 8 | 1.397 | 1.860 | 2.306 | 2.896 | 3.355 |
| 9 | 1.383 | 1.833 | 2.262 | 2.821 | 3.250 |
| 10 | 1.372 | 1.812 | 2.228 | 2.764 | 3.169 |
| 11 | 1.363 | 1.796 | 2.201 | 2.718 | 3.106 |
| 12 | 1.356 | 1.782 | 2.179 | 2.681 | 3.055 |
| 13 | 1.350 | 1.771 | 2.160 | 2.650 | 3.012 |
| 14 | 1.345 | 1.761 | 2.145 | 2.624 | 2.977 |
| 15 | 1.341 | 1.753 | 2.131 | 2.602 | 2.947 |
| ... | ... | ... | ... | ... | ... |
[1] 327.0 335.0 359.0 430.0 275.4 272.0 350.0 343.2 278.0 354.0 303.0 328.0
[13] 371.0 312.0 346.0 359.0 NA 259.0 313.6 258.0 244.0 374.4 NA 338.0
[25] 290.0
| RT | \(f\) |
|---|---|
| 240-259 | 3 |
| 260-279 | 3 |
| 280-299 | 1 |
| 300-319 | 3 |
| 320-339 | 4 |
| 340-359 | 6 |
| 360-379 | 2 |
| 380-399 | 0 |
| 400-419 | 0 |
| 420-439 | 1 |
| \(df\) | \(\alpha = .05\) |
|---|---|
| 1 | 12.706 |
| 2 | 4.303 |
| 3 | 3.182 |
| 4 | 2.776 |
| 5 | 2.571 |
| ... | ... |
| 20 | 2.086 |
| 21 | 2.080 |
| 22 | 2.074 |
| 23 | 2.069 |
| 24 | 2.064 |
| 25 | 2.060 |
| 26 | 2.056 |
| 27 | 2.052 |
| 28 | 2.048 |
| 29 | 2.045 |
| 30 | 2.042 |
| ... | ... |
\(\mu = 284 \\ M = 322.59 \\ SD = 45.31 \\ n = 23\)
\[\begin{align} t = \dfrac{M - \mu}{s_M} &= \dfrac{322.59 - 284}{45.31/\sqrt{23}} \\ &= \dfrac{38.59}{9.45} \\ &= 4.08 \end{align}\]
<!-- jStat = require("https://cdn.jsdelivr.net/npm/jstat@latest/dist/jstat.min.js") -->
cover = {
const w = 1050;
const h = 500;
const duration = 2000; // animation duration per path
const maxDelay = d3.max(test_data, d => d.delay);
// d3 scales for mapping data to canvas space
const tx = d3.scaleLinear()
.domain([-3, 3]) // x range of your t-distributions
.range([0, w]);
const ty = d3.scaleLinear()
.domain([0, 0.4]) // y range of t-distribution densities
.range([h, 0]);
// setup canvas
const devicePixelRatio = window.devicePixelRatio || 1;
const canvas = d3.select("#cover-image")
.append("canvas")
.attr("width", w * devicePixelRatio)
.attr("height", h * devicePixelRatio)
.style("width", `${w}px`) // ensures the CSS size stays the same
.style("height", `${h}px`)
.node();
const ctx = canvas.getContext("2d");
// scale for high DPI
ctx.scale(devicePixelRatio, devicePixelRatio);
ctx.lineWidth = 1;
ctx.lineJoin = "round"; // smooth joins
ctx.lineCap = "round"; // smooth endpoints
// utility: draw a line progressively
function drawPartialPath(ctx, data, color, progress) {
ctx.beginPath();
ctx.strokeStyle = color;
ctx.lineWidth = 2;
// calculate the number of visible points
const totalPoints = Math.floor(progress * data.length);
// slice the data so the visible part shrinks **from the end**
const visibleData = data.slice(-totalPoints);
visibleData.forEach((point, i) => {
const x = tx(point.value);
const y = ty(point.density);
if (i === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
});
ctx.stroke();
}
function animatePaths() {
const start = performance.now();
const delayPerLine = 200;
const maxDelay = delayPerLine * test_data.length;
function step(timestamp) {
const elapsed = timestamp - start;
ctx.clearRect(0, 0, w, h);
test_data.forEach((d, i) => {
const lineStartTime = d.delay;
const lineElapsed = Math.max(0, elapsed - lineStartTime);
const progress = Math.min(lineElapsed / duration, 1);
if (progress > 0) {
// draw forward
drawPartialPathForward(ctx, d.data, d.color, progress);
}
});
if (elapsed < maxDelay + duration) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
function drawPartialPathForward(ctx, data, color, progress) {
ctx.beginPath();
ctx.strokeStyle = color;
ctx.lineWidth = 1;
const totalPoints = Math.floor(progress * data.length);
const visibleData = data.slice(0, totalPoints);
visibleData.forEach((point, i) => {
const x = tx(point.value);
const y = ty(point.density);
if (i === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
});
ctx.stroke();
}
function drawPartialPathReverse(ctx, data, color, progress) {
ctx.beginPath();
ctx.strokeStyle = color;
ctx.lineWidth = 1;
// progress=1 means full line, progress=0 means none.
const startIndex = Math.floor((1 - progress) * data.length);
const visibleData = data.slice(startIndex);
visibleData.forEach((point, i) => {
const x = tx(point.value);
const y = ty(point.density);
if (i === 0) ctx.moveTo(x, y);
else ctx.lineTo(x, y);
});
ctx.stroke();
}
function undrawPaths() {
return new Promise(resolve => {
const start = performance.now();
const maxLineDelay = d3.max(test_data, d => d.delay);
function step(timestamp) {
const elapsed = timestamp - start;
ctx.clearRect(0, 0, w, h);
test_data.forEach((d, i) => {
const lineStartTime = d.delay;
const lineElapsed = Math.max(0, elapsed - lineStartTime);
const progress = Math.min(lineElapsed / duration, 1);
const reverseProgress = 1 - progress;
if (reverseProgress > 0) {
drawPartialPathReverse(ctx, d.data, d.color, reverseProgress);
}
});
// now that line timings depend on d.delay, check if we’ve elapsed enough time
if (elapsed < maxLineDelay + duration) {
requestAnimationFrame(step);
} else {
resolve();
}
}
requestAnimationFrame(step);
});
}
// usage:
canvas.addEventListener("click", () => {
undrawPaths().then(() => {
animatePaths();
});
});
animatePaths();
}