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">
  // We will create n number of data points not bigger than xRange

  const n = 500;
  const xRange = 40;
  const xDomain = [0, 35];
  const dist = { m: 8, sd: 2.5, color: 'red' };

// This will create data points from a normal probability distribution curve o

  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, dist) => {
    const x = xDomain[0] + (xRange * i) / n;
    const y = normPDF(dist.m, dist.sd, x);
    return {
      dist,
      index: i,
      x: x,
      y: 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 = 1000;
  let height = 250;
  const margin = { top: 40, right: 0, bottom: 0, left: 0 };

  export let n = 500;
  const xRange = 40;
  const xDomain = [0, 35];

  // Make the scales reactive to size change (i.e width) note the "$" notation
  $: 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, 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, dist) => {
    const x = xDomain[0] + (xRange * i) / n;
    const y = normPDF(dist.m, dist.sd, x);
    return {
      dist: dist,
      index: i,
      x: x,
      y: y
    };
  };

  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.