Create a Normal Distribution Curve

Let’s write a function to create the data for our visualisation. I would like to chart a normal distribution curve with a mean m and a standard deviation of sd

Create the data

<script lang="ts">const n = 500;
const xRange = 40;
const xDomain = [0, 35];
const dist = { m: 8, sd: 2.5, color: "red" };
const normPDF = (m, sd, x) => {
  const numerator = Math.exp(-Math.pow(x - m, 2) / (2 * Math.pow(sd, 2)));
  const denominator = sd * Math.sqrt(2 * Math.PI);
  return numerator / denominator;
};
const createDatum = (i, dist2) => {
  const x = xDomain[0] + xRange * i / n;
  const y = normPDF(dist2.m, dist2.sd, x);
  return {
    dist: dist2,
    index: i,
    x,
    y
  };
};
const data = new Array(n + 1).fill(0);
$: data.forEach((datum, i) => {
  data[i] = createDatum(i, dist);
});
</script>

<!-- Show a sample of data we just created -->
{#each data.slice(50, 60) as d}
  <div class="pb-1">{JSON.stringify(d, null, 2)}</div>
{/each}
</script>

Let’s print a piece of the data we just created:

{ "dist": { "m": 8, "sd": 2.5, "color": "red" }, "index": 50, "x": 4, "y": 0.04436833387178223 }
{ "dist": { "m": 8, "sd": 2.5, "color": "red" }, "index": 51, "x": 4.08, "y": 0.04667524852055666 }
{ "dist": { "m": 8, "sd": 2.5, "color": "red" }, "index": 52, "x": 4.16, "y": 0.049051855493194 }
{ "dist": { "m": 8, "sd": 2.5, "color": "red" }, "index": 53, "x": 4.24, "y": 0.05149671472582249 }
{ "dist": { "m": 8, "sd": 2.5, "color": "red" }, "index": 54, "x": 4.32, "y": 0.054008098843573736 }
{ "dist": { "m": 8, "sd": 2.5, "color": "red" }, "index": 55, "x": 4.4, "y": 0.05658398608993554 }
{ "dist": { "m": 8, "sd": 2.5, "color": "red" }, "index": 56, "x": 4.48, "y": 0.05922205445026807 }
{ "dist": { "m": 8, "sd": 2.5, "color": "red" }, "index": 57, "x": 4.56, "y": 0.0619196770646263 }
{ "dist": { "m": 8, "sd": 2.5, "color": "red" }, "index": 58, "x": 4.64, "y": 0.06467391902016778 }
{ "dist": { "m": 8, "sd": 2.5, "color": "red" }, "index": 59, "x": 4.72, "y": 0.06748153560757181 }

Plot the chart

Now it’s time to plot that data:

<script lang="ts">import { scaleLinear } from "d3-scale";
let width = 1e3;
let height = 250;
const margin = { top: 40, right: 0, bottom: 0, left: 0 };
export let n = 500;
const xRange = 40;
const xDomain = [0, 35];
$: x = scaleLinear().domain(xDomain).range([margin.left, width - margin.right]);
$: y = scaleLinear().domain([0, 0.15]).range([height - margin.bottom, margin.top]);
const dist = { m: 8, sd: 2.5, color: "red" };
const normPDF = (m, sd, x2) => {
  const numerator = Math.exp(-Math.pow(x2 - m, 2) / (2 * Math.pow(sd, 2)));
  const denominator = sd * Math.sqrt(2 * Math.PI);
  return numerator / denominator;
};
const createDatum = (i, dist2) => {
  const x2 = xDomain[0] + xRange * i / n;
  const y2 = normPDF(dist2.m, dist2.sd, x2);
  return {
    dist: dist2,
    index: i,
    x: x2,
    y: y2
  };
};
let data;
$: data = new Array(n + 1).fill(0);
$: data.forEach((datum, i) => {
  data[i] = createDatum(i, dist);
});
</script>

<svg viewBox="0 0 896 300" width="896px" height="300px">
  {#if data}
    {#each data as d}
      <circle cx={x(d.x)} cy={y(d.y)} r="1" fill="red" />
    {/each}
  {/if}
</svg>

Here is how our data points look like:

In the next step we will use these kind of data to create a normal distribution curve and animating between distributions.