Public
Edited
May 23, 2022
Importers
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// sortInclusion = {
// const container = d3.select(
// html`<div style="display: block; position:relative;" class="container"></div>`
// )
// const legend = container.append('svg')
// .attr("width", 200)
// .attr("height", 80)
// .style("transform", "translate(0px, 0px)")
// .attr("overflow", "visible")
// .attr("class", "legend")
// .attr("aria-label", "legend")

// let legendInclusion = [
// { type: 'inclusive', color: colors[0], description: '80% or more', metric: "eighty" },
// { type: 'semi-inclusive', color: colors[1], description: 'between 40% and 80%', metric: "between" },
// { type: 'non-inclusive', color: colors[2], description: '40% or less', metric: "forty" },
// { type: 'separate', color: colors[3], description: 'separate (hospital, etc.)', metric: "separate" }
// ]

// const inclusion = legend.append('g')
// .attr('transform', 'translate(0, 0)')

// const labelColors = inclusion.append('g')
// .selectAll('rect')
// .data(legendInclusion)
// .join('rect')
// .attr('class', 'inclusionLegend')
// .attr('x', 0)
// .attr('y', (d, i) => -10 + i * 24)
// .attr('width', 12)
// .attr('height', 12)
// .attr('fill', d => d.color)
// .on('click', sortByInclusion)

// const labels = inclusion.append('g')
// .selectAll('text')
// .data(legendInclusion)
// .join('text')
// .attr('class', 'inclusionLegend')
// .attr('text-anchor', 'start')
// .attr('x', 20)
// .attr('y', (d, i) => i * 24)
// .attr('fill', "#555555")
// .text(d => d.type)
// .attr('font-size', '15px')
// .on('click', sortByInclusion)

// function sortByInclusion() {
// let metric = d3.select(this).datum().metric
// let sortedData = [...data].sort((a, b) => metric === "eighty" ? b[metric] - a[metric] : a[metric] - b[metric])

// mutable data = sortedData
// }

// return container.node()
// }
Insert cell
// // Modified from https://observablehq.com/@clhenrick/tooltip-d3-convention

// tooltip = (selectionGroup, tooltipDiv) => {
// // padding between the tooltip and mouse cursor
// const MOUSE_POS_OFFSET = 8

// selectionGroup.each(function () {
// d3.select(this)
// .on("mouseover.tooltip", handleMouseover)
// .on("mousemove.tooltip", handleMousemove)
// .on("mouseleave.tooltip", handleMouseleave);
// });

// function handleMouseover() {
// // show/reveal the tooltip, set its contents,
// showTooltip();
// setContents(d3.select(this).datum());
// }

// function handleMousemove(event) {
// // update the tooltip's position
// const target = this.parentElement.parentElement.parentElement.parentElement
// const [mouseX, mouseY] = d3.pointer(event, target)
// //const [mouseX, mouseY] = [event.clientX, event.clientY]
// // add the left & top margin values to account for the SVG g element transform
// setPosition(mouseX + margin.left, mouseY + margin.top);
// }

// function handleMouseleave() {
// // do things like hide the tooltip
// hideTooltip();
// }

// function showTooltip() {
// tooltipDiv.style("display", "block");
// }

// function hideTooltip() {
// tooltipDiv.style("display", "none");
// }

// function setPosition(mouseX, mouseY) {
// tooltipDiv
// .style(
// "top",
// mouseY < height / 2
// ? `${mouseY + 2 * MOUSE_POS_OFFSET}px`
// : "initial"
// )
// .style(
// "right",
// mouseX > width / 2
// ? `${width - mouseX + MOUSE_POS_OFFSET}px`
// : "initial"
// )
// .style(
// "bottom",
// mouseY > height / 2
// ? `${height - mouseY + 2 * MOUSE_POS_OFFSET}px`
// : "initial"
// )
// .style(
// "left",
// mouseX < width / 2
// ? `${mouseX + MOUSE_POS_OFFSET}px`
// : "initial"
// );
// }

// function setContents(datum) {
// let currentFill
// d3.selectAll(".pieSlice").each(function(d, i) {
// if(d == datum) {
// let current = d3.select(this).attr("style")
// currentFill = current.slice(6)
// }
// })

// function tooltipText() {
// return `<span style="font-size:1rem; font-weight:bold; color:${currentFill} filter:brightness(85%);">${formatDec(datum.data.value)}%</span> of students are in ${datum.data.type === "inclusive" ? "an" : "a"} <br> <span style="font-size:1rem; font-weight:bold; color:${currentFill} filter:brightness(85%);">${datum.data.type}</span> setting`
// }
// tooltipDiv.html(tooltipText)
// }
// }
Insert cell
// sortAlerts = {
// const container = d3.select(
// html`<div style="display: block; position:relative;" class="container"></div>`
// )
// const legend = container.append('svg')
// .attr("width", 200)
// .attr("height", 20)
// .style("transform", "translate(0px, 0px)")
// .attr("overflow", "visible")
// .attr("class", "legend")
// .attr("aria-label", "legend")

// const alertLegend = legend.append("text")
// .attr('transform', 'translate(2, 0)')
// //.attr('fill', 'crimson')
// .attr('fill', alertColor)
// .attr('font-size', '20px')
// .style("text-anchor", "start")
// .attr('font-weight', 'bold')
// .text('!')
// .attr('id', "alertsLegend")
// .on("click", sortByAlerts)

// const alertsLabel = legend.node().appendChild(
// createSVGtext({
// text: "# of alerts",
// x: 14,
// y: 0,
// fontSize: 15,
// color: '#555555',
// textAnchor: "start",
// maxCharsPerLine: 38,
// lineHeight: 1.3,
// //font_weight: "bold",
// textId: "alertsLegend",
// font_family: "Inter"
// })
// )
// d3.select(alertsLabel)
// .attr('transform', 'translate(7, 32)')
// .on("click", sortByAlerts)

// function sortByAlerts() {
// let sortedData = [...data].sort((a, b) => b.nAlerts - a.nAlerts)

// mutable data = sortedData
// }

// return container.node()
// }
Insert cell
// sortNumber = {
// const container = d3.select(
// html`<div style="display: block; position:relative;" class="container"></div>`
// )
// const legend = container.append('svg')
// .attr("width", 200)
// .attr("height", 5)
// .style("transform", "translate(0px, 0px)")
// .attr("overflow", "visible")
// .attr("class", "legend")
// .attr("aria-label", "legend")

// const numberLabel = legend.node().appendChild(
// createSVGtext({
// text: "# students",
// x: 0,
// y: 0,
// fontSize: 18,
// color: '#555555',
// textAnchor: "start",
// textId: "numberSort",
// maxCharsPerLine: 24,
// lineHeight: 1,
// font_weight: "bold",
// font_family: "Inter"
// })
// )
// d3.select(numberLabel)
// .attr('transform', 'translate(0, 40)')
// .on("click", sortByNumber)

// function sortByNumber() {
// let sortedData = [...data].sort((a, b) => a.students && b.students !== null ? b.students - a.students : null)

// mutable data = sortedData
// }

// const numberLabel2 = legend.node().appendChild(
// createSVGtext({
// text: "with IEPs",
// x: 98,
// y: 0,
// fontSize: 14,
// color: '#555555',
// textAnchor: "start",
// maxCharsPerLine: 24,
// lineHeight: 1,
// font_family: "Inter"
// })
// )
// d3.select(numberLabel2).attr('transform', 'translate(0, 40)')

// return container.node()
// }
Insert cell
// viewof similar = Inputs.select(
// orDataSorted,
// {
// format: d => d.name,
// label: "Add districts similar in size to: ",
// value: orDataSorted[orDataSorted.length - 1]
// }
// )
Insert cell
// addSimilar = {
// //let sortedByNumber = await or_data_shape_merged.sort((a, b) => b.students - a.students)
// let index = orDataSortedByNumber.indexOf(similar)
// let length = orDataSortedByNumber.length
// let range

// if (index > length - 6) {
// range = [length - 11, length - 1]
// } else if (index > 5) {
// range = [index - 5, index + 5]
// } else {
// range = [0, 10]
// }

// let similarDistricts = orDataSortedByNumber.filter((d, i) => (i >= range[0] && i <= range[1]))

// similarDistricts.forEach(district => mutable data.push(district))
// //similarDistricts.forEach(district => data.indexOf(district) === -1 ? mutable data.push(district) : null)

// }
Insert cell
//orDataSortedByNumber = or_data_shape_merged.sort((a, b) => b.students - a.students)
Insert cell
//mutable data = await Promises.delay(0, selectedDistricts)
Insert cell
// legendChart = {
// let legendWidth = 400
// let legendHeight = 350
// let legendHeightCenter = legendHeight * 0.65
// const legend = d3.create('svg')
// .attr("width", legendWidth)
// .attr("height", legendHeight)
// .attr("aria-label", "legend")

// const legendBounds = legend.append('g')
// .attr('text-anchor', 'middle')
// .attr('width', legendWidth)
// .attr('height', legendHeight)
// //.style("transform", `translate(${donutMargin.left}px, ${donutMargin.top}px`)

// let legendData = [
// { type: 'inclusive', value: 75 },
// { type: 'semi-inclusive', value: 12 },
// { type: 'non-inclusive', value: 8 },
// { type: 'separate', value: 5 }
// ]

// let legendArcs = pie(legendData)
// let legendScale = d3.scaleOrdinal(legendArcs.map(d => d), colors)

// const legendArc = d3.arc()
// .innerRadius(0.7 * 180 / 2)
// .outerRadius(180 / 2)

// // Legend donut
// const legendDonut = legendBounds.append('g')
// //.attr('class', 'donut-container')
// .attr('transform', `translate(${legendWidth / 2}, ${legendHeightCenter})`)
// .selectAll('path')
// .data(legendArcs)
// .join('path')
// .style('fill', d => legendScale(d.data.type))
// .attr('d', legendArc)
// //.attr('class', 'pieSlice')

// // Label with district's name
// const districtName = legendBounds.node().appendChild(
// createSVGtext({
// text: "School District Name",
// x: `${legendWidth / 2}`,
// y: 20,
// fontSize: 22,
// fill: '#555555',
// textAnchor: "middle",
// maxCharsPerLine: 16,
// lineHeight: 1.2,
// textClass: "donutName",
// font_weight: "bold",
// font_family: "Inter",
// align_to_bottom: "true"
// })
// )

// // Label with student count
// const numberStudents = legendBounds.append("g")
// .attr("transform", `translate(${legendWidth / 2}, ${legendHeightCenter - 15})`)
// .append('text')
// .style("font-size", "21px")
// .style("text-anchor", "middle")
// .attr('font-weight', 'bold')
// .attr('font-family', 'Inter')
// .attr('fill', '#555555')
// .text('# students')

// const studentsLabel = legendBounds.append("g")
// .attr("transform", `translate(${legendWidth / 2}, ${legendHeightCenter + 5})`)
// .append('text')
// .style("font-size", "15px")
// .style("text-anchor", "middle")
// .attr('font-family', 'Inter')
// .attr('font-weight', 'bold')
// .attr('fill', '#555555')
// .text("with IEPs")


// // Alerts
// const alert = legendBounds.append("g")
// .attr("class", 'alert')
// .attr('transform', `translate(${legendWidth / 2}, ${legendHeightCenter + 40})`)
// .append('text')
// .attr('fill', 'red')
// .attr('font-size', '25px')
// .style("text-anchor", "middle")
// .attr('font-weight', 'bold')
// .attr('font-family', 'Inter')
// .text('! ! ! !')

// // Labels
// const inclusiveLabel = legendBounds.node().appendChild(
// createSVGtext({
// text: "% in inclusive setting",
// x: `${legendWidth / 2 + 120}`,
// y: `${legendHeightCenter - 75}`,
// fontSize: 15,
// fill: mainColor,
// textAnchor: "middle",
// textClass: "legendLabel",
// maxCharsPerLine: 16,
// lineHeight: 1,
// font_weight: "bold",
// font_family: "Inter"
// })
// )

// const semiInclusiveLabel = legendBounds.node().appendChild(
// createSVGtext({
// text: "% in semi-inclusive setting",
// x: `${legendWidth / 2 - 150}`,
// y: `${legendHeightCenter - 30}`,
// fontSize: 15,
// fill: "gold",
// textAnchor: "middle",
// textClass: "legendLabel",
// maxCharsPerLine: 16,
// lineHeight: 1,
// font_weight: "bold",
// font_family: "Inter"
// })
// )

// const nonInclusiveLabel = legendBounds.node().appendChild(
// createSVGtext({
// text: "% in non-inclusive setting",
// x: `${legendWidth / 2 - 120}`,
// y: `${legendHeightCenter - 90}`,
// fontSize: 15,
// fill: "orange",
// textAnchor: "middle",
// textClass: "legendLabel",
// maxCharsPerLine: 20,
// lineHeight: 1,
// font_weight: "bold",
// font_family: "Inter"
// })
// )

// const separateLabel = legendBounds.node().appendChild(
// createSVGtext({
// text: "% of students in a separate setting",
// x: `${legendWidth / 2}`,
// y: `${legendHeightCenter - 125}`,
// fontSize: 15,
// fill: "red",
// textAnchor: "middle",
// textClass: "legendLabel",
// maxCharsPerLine: 20,
// lineHeight: 1,
// font_weight: "bold",
// font_family: "Inter"
// })
// )

// const alertsLabel = legendBounds.node().appendChild(
// createSVGtext({
// text: "alerts for excessive discipline or disproportionate racial representation in Special Education",
// x: `${legendWidth / 2 + 250}`,
// y: `${legendHeightCenter + 50}`,
// fontSize: 15,
// fill: "red",
// textAnchor: "middle",
// textClass: "legendLabel",
// maxCharsPerLine: 36,
// lineHeight: 1,
// font_weight: "bold",
// font_family: "Inter"
// })
// )

// const alertLine = legendBounds.append("line")
// .attr('x1', `${legendWidth / 2 + 35}`)
// .attr('x2', `${legendWidth / 2 + 125}`)
// .attr('y1', `${legendHeightCenter + 30}`)
// .attr('y2', `${legendHeightCenter + 45}`)
// .attr('stroke', 'red')
// .attr('stroke-width', '2px')
// .attr('class', "legendLabel")

// return legend.node()
// }
Insert cell
// A holder for the selected district's data

//mutable districtData = []
//districtData = or_data_shape_merged.filter(d => d.name === selectedDistrict)
//districtData = or_data_shape_merged.sort((a, b) => a.name && b.name !== null ? a.name.localeCompare(b.name) : 0).slice(20, 30)
// districtData = or_data_shape_merged.sort((a, b) => b.students - a.students).filter(d => {
// return d.students > numberRange[0] && d.students < numberRange[1]
// })
// districtData = or_data_shape_merged.sort((a, b) => a.name && b.name !== null ? a.name.localeCompare(b.name) : 0).filter(d => {
// return d.students > numberRange[0] && d.students < numberRange[1]
// })
//districtData = or_data_shape_merged.filter(d => d.name === "Winston-Dillard SD 116" || d.name === "Corvallis SD 509J" || d.name === "Crow-Applegate-Lorane SD 66")
Insert cell
// viewof numberRange = rangeSlider({
// min: 0,
// max: 7010,
// value: this ? this.value : [1000, 7010],
// color: mainColor,
// title: 'filter by number of students with IEPs',
// precision: 0
// })
Insert cell
//FileAttachment("merged3.csv").csv()
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more