Creating a stacked area chart

I’m a bit stuck on how to create a stacked area chart – the part I’m stuck on is how to properly use the d3.stack( ) function. I’ve trying scouring guides and Mike’s examples but am still spinning in my wheels.

Essentially, what I have is an array with 1000 rows and 3 columns:

where each column represents a “category”. Since I’m modeling the SIR for epidemiology, column 1 would be the ‘susceptible’ group, column 2 would be the ‘infected group’, and column 3 would be the ‘recovered’ group.

Here’s my notebook: SIR Model Stacked Area / William Pang / Observable

(which builds on the work I’ve done here: SIR Model / William Pang / Observable)

Most of the examples out there seem to use the key function with already defined categorial names, but mine is just an array of results that are generated by computing the numerical solution for a bunch of equations.

My goal is to create a graph where there is a zero baseline and the values for each point add up so the topline is always 1 (e.g. Susceptible + Infected + Recovered = 0.989 + 0.011 + 0 = 1)

Any help would be appreciated! The goal is to create a stacked area graph similar to what 3blue1brown has done (Simulating an epidemic - YouTube)

d3.stack uses keys to distinguish “series”—in your case the keys seem to be 0, 1, and 2, and you should be able to get the stacked values like so:

stackedData = d3.stack().keys([0,1,2])(results)

Note that in Plot the stacking API is much easier to use, if you haven’t played with it yet. You could try to flatten the data:

flatData = results.flatMap(([s, i, r], t) => [
  { type: "s", value: s, time: t },
  { type: "i", value: i, time: t },
  { type: "r", value: r, time: t }

then plot like so:

  marks: [Plot.areaY(flatData, { x: "time", fill: "type", y: "value" })]

(AreaY marks are implicitly stacked).