= FileAttachment("chapter2_sigtests.csv").csv({ typed: true })
sigData
= sigData.filter(
sigsDrug => drug === select
({ drug })
)
= sigsDrug.filter(({ time }) => time === radio[0].time)
significance significance
Documentation
Adult and Young Adult Substance Use Dashboard
Significance Tests
Significance Legend in Graph
= html`<style>
sigLegend1 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>`
= html`<style>
sigLegend2 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>`
= significance[1]?.oneyrchange === undefined ? sigLegend1 : sigLegend2
sigLegend
= {if (radio[0]?.drug == "Alcohol" && radio[0]?.time == "12 Month"){
legendPlace 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
= html`
wideTable <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
= Inputs.table(tablesTime, {
longTable 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
})
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>` citation
Footnotes
= FileAttachment("Footnotes.csv").csv({ typed: true })
footnotesData
= footnotesData.filter(
footnotesFiltered => drug.toLocaleLowerCase() === select.toLocaleLowerCase()
({ drug })
)
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>`;
}
}
= checkFootnote(footnotesFiltered)
footnotes
html`${footnotes}`
Table Data
= FileAttachment("final_table_data.csv").csv({ typed: true })
tables
= {
tablesFormatted const tables2 = tables.map(
, 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: 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?.toLocaleLowerCase() === select?.toLocaleLowerCase()
({ drug }) ;
)
}
= tablesFormatted.filter(({ time }) => time === radio[0].time)
tablesTime
tablesTime
Plot Data
= d3.timeParse("%Y")
parser
= d3.format(".4")
format
= FileAttachment("final_graph2_data.csv").csv({ typed: true })
raw = raw.sort((a, b) => {
rawAlphabetical if (a.drug && b.drug) {
return a.drug.localeCompare(b.drug);
else {
} return 0; // Preserve the order if 'name' is missing
};
})
rawAlphabetical
= rawAlphabetical.filter(thing => thing.drug != null)
prevalence
= {
data const subset = prevalence.map(
, drug, estimate, age, time, flag }) => ({
({ yearyear: parser(year),
year2: format(year),
estimate: +estimate,
drug: drug,
age: age,
time: time,
flag: flag
});
)
const filtered = subset.filter(thing =>
.drug?.toLocaleLowerCase() === select?.toLocaleLowerCase()
thing;
)
return filtered;
}
data
radio
Search Bar
import {PersistInput} from "@john-guerra/persist-input@latest"
import {aq, op} from "@uwdata/arquero"
= aq // viewof shows the table view, but assigns the table value
viewof drugs .fromCSV(await FileAttachment("substance-use-graphs.csv").text())
.groupby("drug")
.count()
.view({ height: 240 })
= drugs.objects()
drugSelection
= PersistInput(
viewof search "drug",
.text({
Inputsdatalist: drugSelection.map((d) => d.drug),
placeholder: "Enter drug name",
submit: true,
label: "Search Drug:",
autocomplete: false,
spellcheck: true,
width: 350
}) )
Dropdown Input
= PersistInput("drug",
viewof select .select(
Inputs.map((d) => d.drug),
prevalence
{value: "Alcohol",
width: 175,
unique: true
} ))
Plot Title
= significance.length > 1
ageQuestion ? "Respondents Aged 19 through 65"
: "Respondents Aged 19 through 30"
Rendered Plot for Combined Age Groups
import {addTooltips} from "@mkfreeman/plot-tooltip"
= d3.timeFormat("%Y")
formatter
= d3.scaleOrdinal(
color "Age 19-30", "Age 35-50", "Age 55-65"],
["#59bbeb", "#6ac4a1", "#cca438"]
[
)
= d3.scaleOrdinal(
symbol "Age 19-30", "Age 35-50", "Age 55-65"],
["circle", "square", "triangle"]
[
)
= radio.filter(d => d.year > new Date("1988-01-01"));
dateFilter1 = radio.filter(d => d.year > new Date("2008-01-01"));
dateFilter2 = radio.filter(d => d.year > new Date("2023-01-01"));
dateFilter3 = dateFilter1.filter(d => d.age === "Age 19-30");
legendFilter1 = dateFilter2.filter(d => d.age === "Age 35-50");
legendFilter2 = dateFilter3.filter(d => d.age === "Age 55-65");
legendFilter3
= [...legendFilter1, ...legendFilter2, ...legendFilter3];
legendData legendData
= addTooltips(
plot .plot({
PlotariaLabel: "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: [
.ruleY([0]),
Plot.dot(legendData, {
Plotx: "year",
y: "estimate",
r: 4,
fill: "age",
symbol: "age",
title: (d) => `${d.age} \n ${formatter(d.year)}: ${d.estimate}%`
,
}).line(legendData, {
Plotx: "year",
y: "estimate",
z: (d) => // This creates the line breaks
[.age,
d.flag
d.join(),
]stroke: "age"})
],
})fill: "age" }
{ )
All Ages Heatmap
= radio.filter(d => d.age != "Ages 19-30")
filter1 = filter1.filter(d => d.age != "Ages 35-50")
filter2
= addTooltips(Plot.plot({
plot2 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: [
.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}%`})
Plot
],
})fill: "estimate"}
{ )
Combined Sig Plot with Legend
= html`
comboPlot <div style="position: relative;">
${plot}
<div style="position: absolute; ${legendPlace} border: solid 1px black;">
${sigLegend}
</div>
</div>`