function normalPDF(x, mu, sigma) {
const coef = 1 / (sigma * Math.sqrt(2 * Math.PI));
const exponent = -Math.pow(x - mu, 2) / (2 * Math.pow(sigma, 2));
return coef * Math.exp(exponent);
}
// Generate x values centered around mu
x_range = d3.range(mu - 4 * sigma, mu + 4 * sigma + 0.1, 0.1)
// Calculate PDF values
pdf_data = x_range.map(x => ({
x: x,
pdf: normalPDF(x, mu, sigma)
}))
// Shaded regions for empirical rule
region_1sd = x_range.filter(x => x >= mu - sigma && x <= mu + sigma).map(x => ({
x: x,
pdf: normalPDF(x, mu, sigma)
}))
region_2sd = x_range.filter(x => x >= mu - 2*sigma && x <= mu + 2*sigma).map(x => ({
x: x,
pdf: normalPDF(x, mu, sigma)
}))
Plot.plot({
width: 800,
height: 450,
marginLeft: 60,
marginBottom: 50,
x: {
label: "Y (random variable)",
grid: true,
domain: [-30, 30]
},
y: {
label: "Probability Density f(y)",
domain: [0, normalPDF(mu, mu, sigma) * 1.1]
},
marks: [
Plot.areaY(region_2sd, {
x: "x",
y: "pdf",
fill: "red",
opacity: 0.3
}),
Plot.areaY(region_1sd, {
x: "x",
y: "pdf",
fill: "steelblue",
opacity: 0.4
}),
Plot.line(pdf_data, {
x: "x",
y: "pdf",
stroke: "darkblue",
strokeWidth: 3
}),
Plot.ruleX([mu], {
stroke: "red",
strokeWidth: 2,
strokeDasharray: "5,5"
}),
Plot.ruleY([0])
],
caption: html`<span style="color: darkblue; font-weight: bold;">โโ</span> N(ฮผ=${mu.toFixed(1)}, ฯ=${sigma.toFixed(1)}) |
<span style="color: steelblue;">โ</span> ยฑ1ฯ (68%) |
<span style="color: lightblue;">โ</span> ยฑ2ฯ (95%) |
<span style="color: red;">โ</span> Mean`
})