- Probability district exceeds national rate — by student group
-
-
-
-
-
- {computed.length === 0 ? (
-
No model data available for the selected groups.
- ) : (
-
- )}
-
-
- Based on the {selectedModel === 'unified_m2_mod' ? 'one-year + covariate model (recommended)' : 'three-year + covariate model'}.
- Green bars indicate groups where this district's rate is unlikely to exceed the national average; red indicates likely exceedance.
-
-
- )
-}
diff --git a/src/charts/ModelDrawsComparison.jsx b/src/charts/ModelDrawsComparison.jsx
deleted file mode 100644
index e867c15..0000000
--- a/src/charts/ModelDrawsComparison.jsx
+++ /dev/null
@@ -1,143 +0,0 @@
-import { MODEL_QUADRANTS } from '../hooks/useApi.js'
-import ChartLegend from '../components/ChartLegend.jsx'
-import { OBSERVED_MARK_COLOR, MODELED_AGGREGATE_COLOR } from '../utils/colors.js'
-
-/**
- * Chart 4: Modeled vs. observed arrests, faceted by the four model-quadrant
- * specifications (one-year/three-year × baseline/+referral-rate covariate).
- * Plain SVG (no D3) — the quadrant label already conveys 1yr/3yr, so all
- * four panels share one ink-diamond/navy-point-range convention rather than
- * doubling up with a redundant per-quadrant hue.
- */
-
-const WAVE_LABELS = { '15-16': '2015–16', '17-18': '2017–18', '21-22': '2021–22' }
-const ALL_WAVES = ['15-16', '17-18', '21-22']
-
-/** Sums count_median/lower/upper across every group row for one wave — the
- * modeled counterpart to waveData's observed-arrests sum. Each row is a
- * single race×sex group, so picking just one row (the original bug here)
- * silently reports whichever group happens to come first from the API. */
-function aggregateModeledForYear(rows, year) {
- const yearRows = (rows || []).filter((r) => r.year === year)
- if (yearRows.length === 0) return null
- return {
- median: yearRows.reduce((sum, r) => sum + (r.count_median || 0), 0),
- lower: yearRows.reduce((sum, r) => sum + (r.count_lower || 0), 0),
- upper: yearRows.reduce((sum, r) => sum + (r.count_upper || 0), 0),
- }
-}
-
-export default function ModelDrawsComparison({ data, waves = ALL_WAVES, districtName }) {
- const waveData = waves.map((year) => {
- const rows = (data.waves && data.waves[year]) || []
- return { year, arrests: rows.reduce((sum, r) => sum + (r.observed_arrests || 0), 0) }
- })
-
- const quadModels = (data && data.quadData) || {}
-
- const allValues = waveData.map((d) => d.arrests)
- Object.entries(quadModels).forEach(([model, rows]) => {
- const isThreeYear = model.includes('m3') || model.includes('m4')
- const years = isThreeYear ? ALL_WAVES : ['21-22']
- years.forEach((year) => {
- const agg = aggregateModeledForYear(rows, year)
- if (agg) allValues.push(agg.median, agg.upper)
- })
- })
- const maxArrests = Math.min(Math.max(...allValues, 1), 50) // cap for readability
-
- return (
-
-
- Model predictions vs. observed — by wave & model specification
-
-
-
- {MODEL_QUADRANTS.map((q) => (
-
- ))}
-
-
-
-
-
- Three-year models span all three CRDC waves; one-year models show 2021–22 only.{' '}
- {districtName ? `District: ${districtName}.` : ''}
-
Estimates are from the CRDC School Arrest Rate API (Knowles & Miller 2025). Data shown spans three waves of
- the Civil Rights Data Collection (2015–16, 2017–18, 2021–22) and compares four Bayesian model specifications:
- one-year vs. three-year models with and without referral-rate covariates. All rates are per 1,000 students.
+ the Civil Rights Data Collection (2015–16, 2017–18, 2021–22) and lets you explore four Bayesian model
+ specifications: one-year vs. three-year models with and without referral-rate covariates. All rates are
+ per 1,000 students.
diff --git a/src/components/GroupFilterBar.jsx b/src/components/GroupFilterBar.jsx
deleted file mode 100644
index 9af3b0b..0000000
--- a/src/components/GroupFilterBar.jsx
+++ /dev/null
@@ -1,66 +0,0 @@
-import { raceColor, RACE_LABELS } from '../utils/colors.js'
-
-const RACE_ORDER = ['WH', 'BL', 'HI', 'AM']
-const SEX_ROWS = [
- { sex: 'F', label: 'Female' },
- { sex: 'M', label: 'Male' },
-]
-
-/**
- * Student-group filter: two rows (Female/Male) of 4 race-colored toggle
- * chips. Sex is row position, not color — race owns the color channel, and
- * a chip's color never changes when siblings are toggled.
- */
-export default function GroupFilterBar({ filter }) {
- return (
-