Public
Edited
Mar 12, 2023
Insert cell
Insert cell
{
let w = width;
let h = 1500;
let pad = 30;
let svg = d3
.create("svg")
.attr("width", w)
.attr("height", h)
.style("border", "solid 1px black");

let y_scale = d3
.scaleBand()
.domain(data.map((o) => o.state).reverse())
.range([h - pad, pad])
.padding(0.2);

let max = d3.max(data.map((o) => o.mean));
let x_scale = d3
.scaleLinear()
.domain([0, max])
.range([2 * pad, w - pad]);

let x_axis = svg
.append("g")
.style("font-size", "12px")
.attr("transform", `translate(0,${h - pad})`)
.call(d3.axisBottom(x_scale).ticks(4).tickSizeOuter(0))
.call((g) =>
// Clone a copy of each tick mark and reset the
// x2 property so that these grid lines span the
// figure.
g
.selectAll(".tick line")
.clone()
.attr("y2", -h)
.attr("stroke-opacity", 0.2)
);
x_axis.select("path.domain").attr("stroke", null);

svg
.append("g")
.selectAll("rect")
.data(data)
.join("rect")
.attr("x", (d) => x_scale(0))
.attr("y", (d) => y_scale(d.state))
.attr("width", (d) => x_scale(d.mean) - x_scale(0))
.attr("height", y_scale.bandwidth())
.attr("fill", "steelblue");

let y_axis = svg
.append("g")
.style("font-size", "12px")
.attr("transform", `translate(${2 * pad})`)
.call(d3.axisLeft(y_scale).ticks(5).tickSizeOuter(0));

return svg.node();
}
Insert cell
data = {
let data = await FileAttachment("Data_2-14-2023.csv").csv({ typed: true });
return d3.sort(
Array.from(
d3
.rollup(
data,
(a) => {
let app = d3.sum(
a.map((o) => o["State appropriations (F2021_F1A)"])
);
let students = d3.sum(
a.map((o) => o["Grand total (EF2021 All students total)"])
);
return {
state: a[0]["State abbreviation (HD2021)"],
mean: app / students
};
},

(o) => o["State abbreviation (HD2021)"]
)
.values()
),
(o) => -o.mean
);
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more