Documentation

Adult and Young Adult Substance Use Dashboard

Significance Tests

sigData = FileAttachment("chapter2_sigtests.csv").csv({ typed: true })

sigsDrug = sigData.filter(
  ({ drug }) => drug === select
)

significance = sigsDrug.filter(({ time }) => time === radio[0].time)
significance

Significance Legend in Graph

sigLegend1 = html`<style>
    caption {
      font-size: 9px;
    }

    table {
      margin-bottom: 0.5rem;
    }

    .small td {
        font-size: 9px;
        color: #000066;
    }

</style>
<table class="small" style="width: 250px; ">
  <caption style="color: #000066;"> <b><u>2023 Trends</b></u> </caption>
  <tr>
    <td>Ages 19-30</td>
    <td>1-Year Change</td>
    <td>${significance[0]?.oneyrchange}</td>
    <td>${significance[0]?.sig_oneyr}</td>
  </tr>
  <tr>
    <td> </td>
    <td>5-Year Change</td>
    <td>${significance[0]?.fiveyrchange}</td>
    <td>${significance[0]?.sig_fiveyr}</td>
  </tr>
  <tr style="background-color: white;">
    <td></td>
    <td>10-Year Change</td>
    <td>${significance[0]?.tenyrchange}</td>
    <td>${significance[0]?.sig_tenyr}</td>
  </tr>
</table>`


sigLegend2 = html`<style>
    caption {
      font-size: 9px;
    }

    table {
      margin-bottom: 0.5rem;
    }

   .small td {
        font-size: 9px;
        color: #000066;
    }

</style>
<table class="small" style="width: 250px; ">
  <caption style="color: #000066;"> <b><u>2023 Trends</b></u> </caption>
  <tr>
    <td>Ages 19-30</td>
    <td>1-Year Change</td>
    <td>${significance[0]?.oneyrchange}</td>
    <td>${significance[0]?.sig_oneyr}</td>
  </tr>
  <tr>
    <td> </td>
    <td>5-Year Change</td>
    <td>${significance[0]?.fiveyrchange}</td>
    <td>${significance[0]?.sig_fiveyr}</td>
  </tr>
  <tr style="background-color: white;">
    <td></td>
    <td>10-Year Change</td>
    <td>${significance[0]?.tenyrchange}</td>
    <td>${significance[0]?.sig_tenyr}</td>
  </tr>
  <tr>
    <td>Ages 35-50</td>
    <td>1-Year Change</td>
    <td>${significance[1]?.oneyrchange}</td>
    <td>${significance[1]?.sig_oneyr}</td>
  </tr>
  <tr>
    <td> </td>
    <td>5-Year Change</td>
    <td>${significance[1]?.fiveyrchange}</td>
    <td>${significance[1]?.sig_fiveyr}</td>
  </tr>
  <tr>
    <td></td>
    <td>10-Year Change</td>
    <td>${significance[1]?.tenyrchange}</td>
    <td>${significance[1]?.sig_tenyr}</td>
  </tr>
   <tr>
    <td>Ages 55-65</td>
    <td>1-Year Change</td>
    <td>.</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td> </td>
    <td>5-Year Change</td>
    <td>.</td>
    <td>N/A</td>
  </tr>
  <tr>
    <td></td>
    <td>10-Year Change</td>
    <td>.</td>
    <td>N/A</td>
  </tr>
</table>`

sigLegend = significance[1]?.oneyrchange === undefined ? sigLegend1 : sigLegend2

legendPlace = {if (radio[0]?.drug == "Alcohol" && radio[0]?.time == "12 Month"){
  return "bottom: 60px; right: 50px;";
} else if (radio[0]?.drug == "Alcohol" && radio[0]?.time == "Lifetime") {
  return "bottom: 60px; right: 50px;";
} else if (radio[0]?.drug == "Alcohol" && radio[0]?.time == "30 Day") {
  return "bottom: 60px; right: 50px;";
} else {
  return "top: 50px; right: 50px;";
}
}

legendPlace

Table Wide Format

Code
wideTable = html`
<style>
.branch {overflow-x:scroll; direction: rtl; margin-left:200px;  }
 
td:nth-child(1), th:first-child  { left: 110px; white-space:nowrap; word-wrap: break-word; }
td:nth-child(2), th:nth-child(2) { left: 210px; word-wrap: break-word;} 
td, th { vertical-align: middle;  padding: .5em; color: black; }
th { text-decoration: underline; white-space:nowrap; }  
tr:nth-child(3) {
  background-color: #ADD8E6;
} 

.sticky {position:absolute; width:100px; top:auto; white-space:normal;} 

table {
  direction: ltr;
  border: none;
  border-collapse: collapse;
  text-align: center;
}


/* On screens that are 1720px or less, do this for the table and citation size */

@media screen and (max-width: 1680px) {
  .branch {overflow-x:scroll; direction: rtl; margin-left:190px;  }
td:nth-child(1), th:first-child  {left: 90px; white-space:nowrap; word-wrap: break-word; }
td:nth-child(2), th:nth-child(2) {left: 190px; word-wrap: break-word;}
tr:nth-child(3) {
  background-color: #ADD8E6;
}
}

/* On screens that are 1720px or less, do this for the table */

@media screen and (max-width: 1375px) {
  .branch {overflow-x:scroll; direction: rtl; margin-left:180px;  } 
td:nth-child(1), th:first-child  {left: 65px; white-space:nowrap; word-wrap: break-word; }
td:nth-child(2), th:nth-child(2) {left: 170px; word-wrap: break-word;}
tr:nth-child(3) {
  background-color: #ADD8E6;
}
}


/* On screens that are 992px or less, do this for the table and citation size */

@media screen and (max-width: 992px) {
  .branch {overflow-x:scroll; direction: rtl; margin-left:175px;  } 
td:nth-child(1), th:first-child  {left: 45px; white-space:nowrap; word-wrap: break-word; }
td:nth-child(2), th:nth-child(2) {left: 145px; word-wrap: break-word;}
tr:nth-child(3) {
  background-color: #ADD8E6;
}
}


/* On screens that are 600px or less, do this for table and citation size */
@media screen and (max-width: 600px) {
  .branch {overflow-x:scroll; direction: rtl; margin-left:155px;  } 
td:nth-child(1), th:first-child  {left: 25px; white-space:nowrap; word-wrap: break-word; }
td:nth-child(2), th:nth-child(2) {left: 115px; word-wrap: break-word;}
tr:nth-child(3) {
  background-color: #ADD8E6;
}
}
</style>
<table aria-label="${radio[0].drug}: Trends in ${radio[0].time} Prevalence of Use in 19-30 and 35-50 year olds">
  <tr>
    <th class="sticky" scope="col">Report Interval</th>
    <th class="sticky" scope="col">Age</th>
    <th scope="col">1988</th>
    <th scope="col">1989</th>
    <th scope="col">1990</th>
    <th scope="col">1991</th>
    <th scope="col">1992</th>
    <th scope="col">1993</th>
    <th scope="col">1994</th>
    <th scope="col">1995</th>
    <th scope="col">1996</th>
    <th scope="col">1997</th>
    <th scope="col">1998</th>
    <th scope="col">1999</th>
    <th scope="col">2000</th>
    <th scope="col">2001</th>
    <th scope="col">2002</th>
    <th scope="col">2003</th>
    <th scope="col">2004</th>
    <th scope="col">2005</th>
    <th scope="col">2006</th>
    <th scope="col">2007</th>
    <th scope="col">2008</th>
    <th scope="col">2009</th>
    <th scope="col">2010</th>
    <th scope="col">2011</th>
    <th scope="col">2012</th>
    <th scope="col">2013</th>
    <th scope="col">2014</th>
    <th scope="col">2015</th>
    <th scope="col">2016</th>
    <th scope="col">2017</th>
    <th scope="col">2018</th>
    <th scope="col">2019</th>
    <th scope="col">2020</th>
    <th scope="col">2021</th>
    <th scope="col">2022</th>
  </tr>
  <tr>
    <td class="sticky" >${htmlTables[0]?.time == undefined ? "-" : htmlTables[0]?.time}</td>
    <td class="sticky" >${htmlTables[0]?.age == undefined ? "-" : htmlTables[0]?.age}</td>
    <td>${htmlTables[0]._1988 == "NaN" ? "-" : htmlTables[0]._1988}</td>
    <td>${htmlTables[0]._1989 == "NaN" ? "-" : htmlTables[0]._1989}</td>
    <td>${htmlTables[0]._1990 == "NaN" ? "-" : htmlTables[0]._1990}</td>
    <td>${htmlTables[0]._1991 == "NaN" ? "-" : htmlTables[0]._1991}</td>
    <td>${htmlTables[0]._1992 == "NaN" ? "-" : htmlTables[0]._1992}</td>
    <td>${htmlTables[0]._1993 == "NaN" ? "-" : htmlTables[0]._1993}</td>
    <td>${htmlTables[0]._1994 == "NaN" ? "-" : htmlTables[0]._1994}</td>
    <td>${htmlTables[0]._1995 == "NaN" ? "-" : htmlTables[0]._1995}</td>
    <td>${htmlTables[0]._1996 == "NaN" ? "-" : htmlTables[0]._1996}</td>
    <td>${htmlTables[0]._1997 == "NaN" ? "-" : htmlTables[0]._1997}</td>
    <td>${htmlTables[0]._1998 == "NaN" ? "-" : htmlTables[0]._1998}</td>
    <td>${htmlTables[0]._1999 == "NaN" ? "-" : htmlTables[0]._1999}</td>
    <td>${htmlTables[0]._2000 == "NaN" ? "-" : htmlTables[0]._2000}</td>
    <td>${htmlTables[0]._2001 == "NaN" ? "-" : htmlTables[0]._2001}</td>
    <td>${htmlTables[0]._2002 == "NaN" ? "-" : htmlTables[0]._2002}</td>
    <td>${htmlTables[0]._2003 == "NaN" ? "-" : htmlTables[0]._2003}</td>
    <td>${htmlTables[0]._2004 == "NaN" ? "-" : htmlTables[0]._2004}</td>
    <td>${htmlTables[0]._2005 == "NaN" ? "-" : htmlTables[0]._2005}</td>
    <td>${htmlTables[0]._2006 == "NaN" ? "-" : htmlTables[0]._2006}</td>
    <td>${htmlTables[0]._2007 == "NaN" ? "-" : htmlTables[0]._2007}</td>
    <td>${htmlTables[0]._2008 == "NaN" ? "-" : htmlTables[0]._2008}</td>
    <td>${htmlTables[0]._2009 == "NaN" ? "-" : htmlTables[0]._2009}</td>
    <td>${htmlTables[0]._2010 == "NaN" ? "-" : htmlTables[0]._2010}</td>
    <td>${htmlTables[0]._2011 == "NaN" ? "-" : htmlTables[0]._2011}</td>
    <td>${htmlTables[0]._2012 == "NaN" ? "-" : htmlTables[0]._2012}</td>
    <td>${htmlTables[0]._2013 == "NaN" ? "-" : htmlTables[0]._2013}</td>
    <td>${htmlTables[0]._2014 == "NaN" ? "-" : htmlTables[0].drug == "MDMA (Ecstasy)" ? htmlTables[0]._2014 + "†" : htmlTables[0]._2014}</td>
    <td>${htmlTables[0]._2015 == "NaN" ? "-" : htmlTables[0]._2015}</td>
    <td>${htmlTables[0]._2016 == "NaN" ? "-" : htmlTables[0]._2016}</td>
    <td>${htmlTables[0]._2017 == "NaN" ? "-" : htmlTables[0]._2017}</td>
    <td>${htmlTables[0]._2018 == "NaN" ? "-" : htmlTables[0]._2018}</td>
    <td>${htmlTables[0]._2019 == "NaN" ? "-" : htmlTables[0]._2019}</td>
    <td>${htmlTables[0]._2020 == "NaN" ? "-" : htmlTables[0]._2020}</td>
    <td>${htmlTables[0]._2021 == "NaN" ? "-" : htmlTables[0]._2021}</td>
    <td>${htmlTables[0]._2022 == "NaN" ? "-" : htmlTables[0]._2022}</td>
  </tr>
  <tr>
    <td class="sticky" >${htmlTables[1]?.time == undefined ? "-" : htmlTables[1]?.time}</td>
    <td class="sticky" >${htmlTables[1]?.age == undefined ? "-" : htmlTables[1]?.age}</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>-</td>
    <td>${htmlTables[1]?._2008 == "NaN" ? "-" : htmlTables[1]?._2008 == undefined ? "-" : htmlTables[1]?._2008}</td>
    <td>${htmlTables[1]?._2009 == "NaN" ? "-" : htmlTables[1]?._2009 == undefined ? "-" : htmlTables[1]?._2009}</td>
    <td>${htmlTables[1]?._2010 == "NaN" ? "-" : htmlTables[1]?._2010 == undefined ? "-" : htmlTables[1]?._2010}</td>
    <td>${htmlTables[1]?._2011 == "NaN" ? "-" : htmlTables[1]?._2011 == undefined ? "-" : htmlTables[1]?._2011}</td>
    <td>${htmlTables[1]?._2012 == "NaN" ? "-" : htmlTables[1]?._2012 == undefined ? "-" : htmlTables[1]?._2012}</td>
    <td>${htmlTables[1]?._2013 == "NaN" ? "-" : htmlTables[1]?._2013 == undefined ? "-" : htmlTables[1]?._2013}</td>
    <td>${htmlTables[1]?._2014 == "NaN" ? "-" : htmlTables[1]?._2014 == undefined ? "-" : htmlTables[1]?._2014}</td>
    <td>${htmlTables[1]?._2015 == "NaN" ? "-" : htmlTables[1]?._2015 == undefined ? "-" : htmlTables[1]?._2015}</td>
    <td>${htmlTables[1]?._2016 == "NaN" ? "-" : htmlTables[1]?._2016 == undefined ? "-" : htmlTables[1]?._2016}</td>
    <td>${htmlTables[1]?._2017 == "NaN" ? "-" : htmlTables[1]?._2017 == undefined ? "-" : htmlTables[1]?._2017}</td>
    <td>${htmlTables[1]?._2018 == "NaN" ? "-" : htmlTables[1]?._2018 == undefined ? "-" : htmlTables[1]?._2018}</td>
    <td>${htmlTables[1]?._2019 == "NaN" ? "-" : htmlTables[1]?._2019 == undefined ? "-" : htmlTables[1]?._2019}</td>
    <td>${htmlTables[1]?._2020 == "NaN" ? "-" : htmlTables[1]?._2020 == undefined ? "-" : htmlTables[1]?._2020}</td>
    <td>${htmlTables[1]?._2021 == "NaN" ? "-" : htmlTables[1]?._2021 == undefined ? "-" : htmlTables[1]?._2021}</td>
    <td>${htmlTables[1]?._2022 == "NaN" ? "-" : htmlTables[1]?._2022 == undefined ? "-" : htmlTables[1]?._2022}</td>
  </tr>
</table>
`

Table Long Format

longTable = Inputs.table(tablesTime, {
  columns: [
    "year",
    "age_18",
    "age_19_20",
    "age_21_22",
    "age_23_24",
    "age_25_26",
    "age_27_28",
    "age_29_30",
    "age_35",
    "age_40",
    "age_45",
    "age_50",
    "age_55",
    "age_60",
    "age_65"
  ],
  header: {
    year: "Year",
    age_18: "Age 18",
    age_19_20: "Ages 19-20",
    age_21_22: "Ages 21-22",
    age_23_24: "Ages 23-24",
    age_25_26: "Ages 25-26",
    age_27_28: "Ages 27-28",
    age_29_30: "Ages 29-30",
    age_35: "Age 35",
    age_40: "Age 40",
    age_45: "Age 45",
    age_50: "Age 50",
    age_55: "Age 55",
    age_60: "Age 60",
    age_65: "Age 65"
  },
    format: {
    year: d => html`<b>${d}</b>`,
    age_18: d=> d.toFixed(1),
    age_19_20: d=> d.toFixed(1),
    age_21_22: d=> d.toFixed(1),
    age_23_24: d=> d.toFixed(1),
    age_25_26: d=> d.toFixed(1),
    age_27_28: d=> d.toFixed(1),
    age_29_30: d=> d.toFixed(1),
    age_35: d=> d.toFixed(1),
    age_40: d=> d.toFixed(1),
    age_45: d=> d.toFixed(1),
    age_50: d=> d.toFixed(1),
    age_55: d=> d.toFixed(1),
    age_60: d=> d.toFixed(1),
    age_65: d=> d.toFixed(1)
  },
  rows: 75,
  width: 1200
})

Accordion Buttons

accordionButtons = 
html`
<div style="width: 90%" class="accordion accordion-flush" id="accordionFlushExample">
  <div class="accordion-item">
    <h2 class="accordion-header" id="flush-headingOne">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseOne" aria-expanded="false" aria-controls="flush-collapseOne">
        ${radio[0].drug}: Trends in ${radio[0].time} Prevalence Table
      </button>
    </h2>
    <div id="flush-collapseOne" class="accordion-collapse collapse" aria-labelledby="flush-headingOne" data-bs-parent="#accordionFlushExample">
      <div class="accordion-body">
              <div class="center"><div>${longTable}</div></div>
                <div>                      
          </div>
    </div>
  </div>
</div>`

Citation

citation = html`<div style="max-width: 750px;"><p style="font-size: small;">Suggested citation: Patrick, M. E., Miech, R. A., Johnston, L. D., & O’Malley, P. M. (2024). Monitoring the Future Panel Study annual report: National data on substance use among adults ages 19 to 65, 1976-2023. Monitoring the Future Monograph Series. Ann Arbor: Institute for Social Research, The University of Michigan.</p></div>`

Footnotes

footnotesData = FileAttachment("Footnotes.csv").csv({ typed: true })

footnotesFiltered = footnotesData.filter(
  ({ drug }) => drug.toLocaleLowerCase() === select.toLocaleLowerCase()
)

 function checkFootnote(d) {
  if (d.length == 0 ) {
  return html`<div></div>`;
} else if (d.length == 1) {
  return html`<div style="max-width: 750px;"><p style="font-size: small;"><sup>${footnotesFiltered[0]?.superscript}</sup>${footnotesFiltered[0]?.footnote}</p></div>`;
} else {
  return html`<div style="max-width: 750px;"><p style="font-size: small;"><sup>${footnotesFiltered[0]?.superscript}</sup>${footnotesFiltered[0]?.footnote}<br><sup>${footnotesFiltered[1]?.superscript}</sup>${footnotesFiltered[1]?.footnote}</p></div>`;
}
}

footnotes = checkFootnote(footnotesFiltered)

html`${footnotes}`

Table Data

tables = FileAttachment("final_table_data.csv").csv({ typed: true })



tablesFormatted = {
  const tables2 = tables.map(
    ({ time, drug, year, age_18, age_19_20, age_21_22, age_23_24, age_25_26, age_27_28, age_29_30, age_35, age_40, age_45, age_50, age_55, age_60, age_65
 }) => ({
      time: time,
      drug: drug,
      year: formatter(parser(year)),
      age_18: +age_18,
      age_19_20: +age_19_20, 
      age_21_22: +age_21_22, 
      age_23_24: +age_23_24, 
      age_25_26: +age_25_26, 
      age_27_28: +age_27_28, 
      age_29_30: +age_29_30, 
      age_35: +age_35, 
      age_40: +age_40, 
      age_45: +age_45, 
      age_50: +age_50, 
      age_55: +age_55, 
      age_60: +age_60, 
      age_65: +age_65
    })
  );

  return tables2.filter(
    ({ drug }) => drug?.toLocaleLowerCase() === select?.toLocaleLowerCase()
  );
}


tablesTime = tablesFormatted.filter(({ time }) => time === radio[0].time)

tablesTime

Plot Data

parser = d3.timeParse("%Y")

format = d3.format(".4")

raw = FileAttachment("final_graph2_data.csv").csv({ typed: true })
rawAlphabetical = raw.sort((a, b) => {
  if (a.drug && b.drug) {
    return a.drug.localeCompare(b.drug);
  } else {
    return 0; // Preserve the order if 'name' is missing
  }
});

rawAlphabetical
prevalence = rawAlphabetical.filter(thing => thing.drug != null)


data = {
  const subset = prevalence.map(
    ({ year, drug, estimate, age, time, flag }) => ({
      year: parser(year),
      year2: format(year),
      estimate: +estimate,
      drug: drug,
      age: age,
      time: time,
      flag: flag
    })
  );

  const filtered = subset.filter(thing => 
  thing.drug?.toLocaleLowerCase() === select?.toLocaleLowerCase()
);

  return filtered;
}

data
radio

Radio Buttons

viewof radio = {
  const values = d3.group(data, (d) => d.time);
  return Inputs.radio(values, {
    key: values.has("12 Month")
      ? "12 Month"
      : values.keys().next().value
  });
}

Zoom-in Button

function buttonToggle({ 
  onText = "Zoom in",
  offText = "Zoom out",
  value = 0,
  click = (value, clicks) => clicks
} = {}) {
  let text = onText,
    ml = html`<button type="button" class="btn btn-outline-primary">${text}</button>`,
    clicks = 0,
    v = value;

  ml.value = v;
  ml.onclick = () => {
    v = click(v, ++clicks);

    ml.value = v;
    ml.innerHTML = clicks % 2 === 0 ? onText : offText;
  };
  return ml;
}

max = Math.max(...legendData.map((o) => o.estimate))
min = Math.min(...legendData.map((o) => o.estimate))
yAxis = max + (max-min)

max
min
yscale = {
  if (zoomInButton % 2 == 0) {
    return [0, 100]; // If this statement is true, return this
  } else {
    return [0, yAxis]; // If the second statement is true, return this
  }
}

viewof zoomInButton = buttonToggle()

legendData
function dataToggle({ 
  onText = "Show All Age Groups",
  offText = "Show Combined Age Groups",
  value = 0,
  click = (value, clicks) => clicks
} = {}) {
  let text = onText,
    ml = html`<button type="button" class="btn btn-outline-primary">${text}</button>`,
    clicks = 0,
    v = value;

  ml.value = v;
  ml.onclick = () => {
    v = click(v, ++clicks);

    ml.value = v;
    ml.innerHTML = clicks % 2 === 0 ? onText : offText;
  };
  return ml;
}


plots = {
  if (dataSwitchButton % 2 == 0) {
    return comboPlot; // If this statement is true, return this
  } else {
    return plot2; // If the second statement is true, return this
  }
}

html`<div>${plots}</di>`
viewof dataSwitchButton = dataToggle()

Explain this

Download Data Button

downloadButton = (data, filename) => {
  
  let downloadData;
  downloadData = new Blob([d3.csvFormat(data)], { type: "text/csv" });
  const size = (downloadData.size / 1024).toFixed(0);
  const button = DOM.download(
    downloadData,
    filename,
    `Download ${filename} Dataset (~${size} KB)`
  );
  return button;
}

name = `${radio[0].drug} - ${radio[0].time}`

data2 = radio.map(d => ({...d, year: d.year2}))

data3 = data2.map(({year2, ...keep}) => keep)

downloadData = downloadButton(data3, name)

downloadButton is a function that takes an array of data as the first argument and the name you want to call the file as the second argument. It displays the filename and the size of the file in kilobytes.

Plot Title

ageQuestion = significance.length > 1
  ? "Respondents Aged 19 through 65"
  : "Respondents Aged 19 through 30"

Rendered Plot for Combined Age Groups

import {addTooltips} from "@mkfreeman/plot-tooltip"

formatter = d3.timeFormat("%Y")

color = d3.scaleOrdinal(
  ["Age 19-30", "Age 35-50", "Age 55-65"],
  ["#59bbeb", "#6ac4a1", "#cca438"]
)

symbol = d3.scaleOrdinal(
  ["Age 19-30", "Age 35-50", "Age 55-65"],
  ["circle", "square", "triangle"]
)

dateFilter1 = radio.filter(d => d.year > new Date("1988-01-01"));
dateFilter2 = radio.filter(d => d.year > new Date("2008-01-01"));
dateFilter3 = radio.filter(d => d.year > new Date("2023-01-01"));
legendFilter1 = dateFilter1.filter(d => d.age === "Age 19-30");
legendFilter2 = dateFilter2.filter(d => d.age === "Age 35-50");
legendFilter3 = dateFilter3.filter(d => d.age === "Age 55-65");

legendData = [...legendFilter1, ...legendFilter2, ...legendFilter3];
legendData
plot = addTooltips(
  Plot.plot({
    ariaLabel: "Adult and Young Adult Substance Use Line Charts",
    ariaDescription:
      "Drug Prevalence Chart showing estimates of use over time (1975 to 2022) in 19-30 and 35-50 year olds filtered by drug name and reporting interval. Currently showing ${radio[0].drug}",
    width: 900,
    height: 700,
    marginBottom: 50,
    marginLeft: 50,
    style: {
      overflow: "visible",
      fontSize: 12
    },
      symbol: {
      domain: new Set(legendData.map((d) => d.age)),
      range: [...new Set(legendData.map((d) => d.age))].map(symbol),
      legend: true,
      swatchSize: 23
    },
      color: {
      domain: new Set(legendData.map((d) => d.age)),
      range: [...new Set(legendData.map((d) => d.age))].map(color),
    },
    y: {
      label: "Percentage (%)",
      labelAnchor: "center",
      domain: yscale
    },
    x: {
      type: "time",
      domain: [new Date("1987-01-01"), new Date("2024-01-01")],
      label: "Years",
      anchor: "bottom",
      labelAnchor: "center"
    },
    marks: [
      Plot.ruleY([0]),
      Plot.dot(legendData, {
        x: "year",
        y: "estimate",
        r: 4,
        fill: "age",
        symbol: "age",
        title: (d) => `${d.age} \n ${formatter(d.year)}: ${d.estimate}%`
      }),
      Plot.line(legendData, {
        x: "year",
        y: "estimate",
        z: (d) => // This creates the line breaks
          [
            d.age,
            d.flag
          ].join(),
        stroke: "age"})
        ]
  }),
  { fill: "age" }
)

All Ages Heatmap

filter1 = radio.filter(d => d.age != "Ages 19-30")
filter2 = filter1.filter(d => d.age != "Ages 35-50")

plot2 = addTooltips(Plot.plot({
  marginTop: 50,
  marginLeft: 100,  
  width: 1500,
  height: 500,
  grid: true,
  x: {axis: "top", label: "Year", type: "band"},
  y: {label: "Age", domain: ["Ages 19-20", "Ages 21-22", "Ages 23-24", "Ages 25-26", "Ages 27-28", "Ages 29-30", "Age 35", "Age 40", "Age 45", "Age 50", "Age 55", "Age 60"]},
  color: {type: "linear", scheme: "BuRd", legend: true, label: "Drug Use Estimate"},
  marks: [
    Plot.cell(filter2, {x: "year2", y: "age", fill: "estimate", inset: 0.5, title: (d) => `${d.age} \n ${formatter(d.year)}: ${d.estimate}%`}),
    Plot.text(filter2, {x: "year2", y: "age", text: "estimate", stroke: "white", strokeOpacity: 0.7, fill: "black", title: (d) => `${d.age} \n ${formatter(d.year)}: ${d.estimate}%`})
  ]
}),
{fill: "estimate"}
)

Combined Sig Plot with Legend

comboPlot = html`
<div style="position: relative;">
  ${plot}
  <div style="position: absolute; ${legendPlace} border: solid 1px black;">
    ${sigLegend}
  </div>
</div>`