CatalogoDati pubblici ›Riferimento
AI

La scuola in cifre — dashboard per dirigenti e docenti

Cinque fonti ufficiali MIUR e INVALSI in dashboard pensate per chi la scuola la dirige o ci insegna: quanti alunni avrai (non solo quanti ne hai), dove si disperde il percorso, come vanno le prove, in che edifici si studia e con che organico. I dati si incrociano da soli tramite comune, regione o provincia. Nessun dato tuo lascia il dispositivo.

▶ Usa questa app

scuolaistruzionedashboardiscrizionidispersione scolasticaabbandonoedilizia scolasticainvalsidocentiorganicomiuralunniprevisione

Cosa registra

  • Cerca il comune per nome…
  • Trend lineare (default)
  • Nome della regione
  • Nome della provincia
  • Trend lineare (default)

Come funziona

Questa è un'app Reactive: un semplice documento di testo che il browser trasforma in un'app funzionante — moduli, dati dal vivo, tabelle, statistiche e persino grafici, senza installare né configurare nulla.

  1. Usala subito. Premi «Usa questa app»: si apre subito nel tuo browser, già pronta, con i dati salvati solo sul tuo dispositivo.
  2. I tuoi dati restano tuoi. Tutto è memorizzato in locale sul dispositivo, separato per ogni app: niente account, niente server, niente da configurare.
  3. Rendila tua. Il testo qui sotto è l'app per intero: copialo, cambia campi, viste e parole, e le modifiche diventano subito interattive.
  4. Condividila come file. Un'app è un semplice file: salvalo, esportalo o condividilo con un link; e con la collaborazione cifrata più persone modificano gli stessi dati in tempo reale.
Il testo dell'app
# 🎒 La scuola in cifre

Cinque fonti ufficiali MIUR e INVALSI in dashboard pensate per chi la scuola
la dirige o ci insegna: quanti alunni avrai (non solo quanti ne hai), dove si
disperde il percorso, come vanno le prove, in che edifici si studia e con che
organico. I dati si incrociano da soli tramite comune, regione o provincia.
Nessun dato tuo lascia il dispositivo.

:::::page{title="Il mio comune" icon="🏫"}

## Il quadro del tuo territorio

Cerca il comune per nome e **scegli dal menu**: la scheda si aggiorna da
sola.

::input[cercaComune]{value="Bologna" placeholder="Cerca il comune per nome…"}

::od-query{into="comuniTrovati" sql="SELECT codice_istat AS codice_istat, comune || ' (' || sigla || ')' AS etichetta FROM istat_confini_comuni WHERE upper(strip_accents(comune)) LIKE '%' || upper(strip_accents('{#cercaComune}')) || '%' ORDER BY length(comune), comune" limit="20"}

::select-from[comune]{from="comuniTrovati" label="etichetta" value="codice_istat"}

::od-query{into="kpiAlunni" sql="SELECT a.alunni AS alunni, round(100.0*(a.alunni-b.alunni)/b.alunni,1) AS variazione FROM (SELECT sum(alunni) AS alunni FROM iscrizioni_scolastiche WHERE codice_istat='{#comune}' AND anno_scolastico=(SELECT max(anno_scolastico) FROM iscrizioni_scolastiche)) a, (SELECT sum(alunni) AS alunni FROM iscrizioni_scolastiche WHERE codice_istat='{#comune}' AND anno_scolastico=(SELECT min(anno_scolastico) FROM iscrizioni_scolastiche)) b"}

::od-query{into="kpiScuole" sql="SELECT (SELECT count(*) FROM scuole WHERE codice_istat='{#comune}') AS scuole, (SELECT count(*) FROM edilizia_scolastica WHERE codice_istat='{#comune}') AS edifici"}

::od-query{into="kpiEdilizia" sql="SELECT round(avg(anno_costruzione)) AS anno_medio, count(*) FILTER (WHERE classificazione_sismica<=2) AS sismica_alta FROM edilizia_scolastica WHERE codice_istat='{#comune}' AND (anno_costruzione IS NULL OR anno_costruzione BETWEEN 1500 AND 2026)"}

::::grid{cols="3"}
:::cards{path="kpiAlunni" search="false"}
🎓 **{alunni}** alunni oggi — variazione in 10 anni **{variazione}%**
:::
---
:::cards{path="kpiScuole" search="false"}
🏫 **{scuole}** scuole statali in **{edifici}** edifici censiti
:::
---
:::cards{path="kpiEdilizia" search="false"}
🏛️ Anno medio di costruzione **{anno_medio}** — **{sismica_alta}** edifici in zona sismica 1-2
:::
::::

## Quanti alunni avrai: la previsione

Il dato che serve per programmare organico e classi: il trend delle
iscrizioni prolungato in avanti. Muovi lo slider per l'orizzonte (la prima
esecuzione scarica il motore di calcolo, poi si aggiorna da sola).

::od-query{into="trendIscrizioni" sql="SELECT substr(anno_scolastico,1,4)::INTEGER AS anno, sum(alunni) AS alunni FROM iscrizioni_scolastiche WHERE codice_istat='{#comune}' GROUP BY 1 ORDER BY 1"}

::range[anniPrev]{min="1" max="5" value="3" legend="Anni di previsione"}

:::select{id="algoPrev" placeholder="Trend lineare (default)"}
- ARIMA/SARIMA
- Holt-Winters (ETS)
:::

::ml-forecast{data="trendIscrizioni" x="anno" y="alunni" horizon="#anniPrev" model="#algoPrev" into="trendPrev"}

::chart-line{data="trendPrev" x="anno" y="alunni,previsione" height="16rem"}

::od-query{into="gradoComune" sql="SELECT grado AS grado, alunni AS alunni FROM iscrizioni_scolastiche WHERE codice_istat='{#comune}' AND anno_scolastico=(SELECT max(anno_scolastico) FROM iscrizioni_scolastiche) ORDER BY grado"}

:::table{path="gradoComune" headers="Grado,Alunni (ultimo anno)" search="false" pagesize="5"}
{grado} | {alunni}
:::

## Gli edifici, per epoca di costruzione

::od-query{into="periodiComune" sql="SELECT periodo_costruzione AS periodo, count(*) AS edifici FROM edilizia_scolastica WHERE codice_istat='{#comune}' AND periodo_costruzione IS NOT NULL GROUP BY 1 ORDER BY min(coalesce(anno_costruzione,2100))"}

::chart-bar{data="periodiComune" x="periodo" y="edifici" height="16rem"}

## Le scuole del comune

::od-query{into="scuoleComune" sql="SELECT nome AS nome, grado AS grado, indirizzo AS indirizzo FROM scuole WHERE codice_istat = '{#comune}' ORDER BY grado, nome" limit="300"}

:::table{path="scuoleComune" headers="Scuola,Grado,Indirizzo" pagesize="10"}
{nome} | {grado} | {indirizzo}
:::

Le iscrizioni sono solo scuola statale (infanzia esclusa dalla fonte); la
previsione è un trend lineare, non un oracolo — l'R² nello stato dice quanto
il trend spiega la serie. La classificazione sismica va da 1 (rischio più
alto) a 4.

:::::

:::::page{title="Dispersione" icon="📉"}

## L'abbandono scolastico, anno per anno

La serie storica nazionale dall'a.s. 2013/2014: in calo costante per medie e
passaggio tra cicli, con una ripresa nell'ultimo biennio per le superiori.

::od-query{into="trendNazionale" sql="SELECT anno_frequenza AS anno, max(CASE WHEN grado='I grado' THEN tasso_abbandono_perc END) AS medie, max(CASE WHEN grado='passaggio cicli' THEN tasso_abbandono_perc END) AS passaggio, max(CASE WHEN grado='II grado' THEN tasso_abbandono_perc END) AS superiori FROM dispersione_scolastica WHERE regione = 'ITALIA' GROUP BY anno_frequenza ORDER BY anno_frequenza"}

::chart-line{data="trendNazionale" x="anno" y="medie,passaggio,superiori" height="16rem"}

## Il confronto tra regioni — clicca una barra

Tasso di abbandono alle superiori, ultimo biennio disponibile. **Clicca una
regione** per filtrare il dettaglio storico qui sotto (secondo clic: filtro
tolto — è il filtro incrociato dei veri strumenti BI).

::od-query{into="rankingRegioni" sql="SELECT regione AS regione, tasso_abbandono_perc AS tasso FROM dispersione_scolastica WHERE grado = 'II grado' AND anno_frequenza = (SELECT max(anno_frequenza) FROM dispersione_scolastica WHERE regione != 'ITALIA' AND grado = 'II grado') AND regione != 'ITALIA' ORDER BY tasso DESC" limit="20"}

::od-query{into="dispDettaglio" sql="SELECT regione AS regione, grado AS grado, periodo AS periodo, tasso_abbandono_perc AS tasso FROM dispersione_scolastica WHERE regione != 'ITALIA' ORDER BY regione, grado, anno_frequenza" limit="300"}

::::dashboard{path="rankingRegioni"}
::chart-bar{data="rankingRegioni" x="regione" y="tasso" height="20rem"}

:::table{path="dispDettaglio" headers="Regione,Grado,Biennio,Tasso %" pagesize="9"}
{regione} | {grado} | {periodo} | {tasso}
:::
::::

Valle d'Aosta e Trentino-Alto Adige sono assenti dalla fonte ministeriale
per l'intera serie; il dettaglio regionale copre i bienni dal 2015/2016 (il
Ministero non ripubblica gli anni precedenti a ogni nuova edizione).

:::::

:::::page{title="INVALSI" icon="📊"}

## La tua regione, prova per prova

Inserisci una regione: es. `Lombardia`, `Campania`, `Sicilia`, `Veneto`.

::input[regione]{value="Lombardia" placeholder="Nome della regione"}

**Italiano e Matematica in 5ª primaria**, anno per anno:

::od-query{into="trendInvalsi" sql="SELECT anno AS anno, max(CASE WHEN materia='Italiano' THEN round(punteggio_medio,1) END) AS italiano, max(CASE WHEN materia='Matematica' THEN round(punteggio_medio,1) END) AS matematica FROM invalsi_regionale WHERE territorio = '{#regione}' AND grado = '5ª primaria' GROUP BY anno ORDER BY anno"}

::chart-line{data="trendInvalsi" x="anno" y="italiano,matematica" height="16rem"}

**La Matematica lungo il percorso** — 5ª primaria, 3ª media, 5ª superiore:

::od-query{into="trendGradi" sql="SELECT anno AS anno, max(CASE WHEN grado='5ª primaria' THEN round(punteggio_medio,1) END) AS primaria, max(CASE WHEN grado='3ª secondaria I grado' THEN round(punteggio_medio,1) END) AS media, max(CASE WHEN grado='5ª secondaria II grado' THEN round(punteggio_medio,1) END) AS superiore FROM invalsi_regionale WHERE territorio = '{#regione}' AND materia = 'Matematica' GROUP BY anno ORDER BY anno"}

::chart-line{data="trendGradi" x="anno" y="primaria,media,superiore" height="16rem"}

## Il confronto tra regioni — clicca una barra

Matematica, 5ª primaria, ultimo anno. **Clicca una regione** per vedere
tutte le sue prove nel dettaglio sotto.

::od-query{into="rankingInvalsi" sql="SELECT territorio AS regione, round(punteggio_medio,1) AS punteggio FROM invalsi_regionale WHERE livello = 'regione' AND grado = '5ª primaria' AND materia = 'Matematica' AND anno = (SELECT max(anno) FROM invalsi_regionale) ORDER BY punteggio DESC" limit="20"}

::od-query{into="invDettaglio" sql="SELECT territorio AS regione, grado AS grado, materia AS materia, round(punteggio_medio,1) AS punteggio FROM invalsi_regionale WHERE livello = 'regione' AND anno = (SELECT max(anno) FROM invalsi_regionale) ORDER BY territorio, grado, materia" limit="300"}

::::dashboard{path="rankingInvalsi"}
::chart-bar{data="rankingInvalsi" x="regione" y="punteggio" height="20rem"}

:::table{path="invDettaglio" headers="Regione,Grado,Materia,Punteggio" pagesize="10"}
{regione} | {grado} | {materia} | {punteggio}
:::
::::

Dato CAMPIONARIO (un sondaggio su un campione di scuole), scala WLE con
media nazionale ≈200: utile per confronti nel tempo e tra territori, non per
il singolo istituto. A.s. 2019/2020 assente (niente prove, COVID).

:::::

:::::page{title="Organico" icon="👩‍🏫"}

## I docenti della tua provincia

Inserisci una provincia: es. `Milano`, `Roma`, `Napoli`, `Torino`.

::input[provincia]{value="Milano" placeholder="Nome della provincia"}

::od-query{into="kpiDocenti" sql="SELECT a.docenti AS docenti, round(100.0*(a.docenti-b.docenti)/b.docenti,1) AS variazione FROM (SELECT sum(totale) AS docenti FROM personale_scuola WHERE provincia='{#provincia}' AND categoria='Docente' AND anno_scolastico=(SELECT max(anno_scolastico) FROM personale_scuola)) a, (SELECT sum(totale) AS docenti FROM personale_scuola WHERE provincia='{#provincia}' AND categoria='Docente' AND anno_scolastico=(SELECT min(anno_scolastico) FROM personale_scuola)) b"}

::od-query{into="kpiRapporto" sql="SELECT round(a.alunni::DOUBLE / p.docenti, 1) AS rapporto FROM (SELECT sum(alunni) AS alunni FROM iscrizioni_scolastiche WHERE provincia = '{#provincia}' AND anno_scolastico = (SELECT max(anno_scolastico) FROM iscrizioni_scolastiche)) a, (SELECT sum(totale) AS docenti FROM personale_scuola WHERE provincia = '{#provincia}' AND categoria = 'Docente' AND anno_scolastico = (SELECT max(anno_scolastico) FROM personale_scuola)) p"}

::od-query{into="kpiSostegno" sql="SELECT round(100.0*(sum(totale) FILTER (WHERE tipo_posto='Sostegno'))/sum(totale),1) AS perc_sostegno, (SELECT sum(totale) FROM personale_scuola WHERE provincia='{#provincia}' AND categoria='ATA' AND anno_scolastico=(SELECT max(anno_scolastico) FROM personale_scuola)) AS ata FROM personale_scuola WHERE provincia='{#provincia}' AND categoria='Docente' AND anno_scolastico=(SELECT max(anno_scolastico) FROM personale_scuola)"}

::::grid{cols="3"}
:::cards{path="kpiDocenti" search="false"}
👩‍🏫 **{docenti}** docenti titolari — variazione in 10 anni **{variazione}%**
:::
---
:::cards{path="kpiRapporto" search="false"}
👥 **{rapporto}** alunni per docente (iscrizioni ÷ titolari, ultimo anno)
:::
---
:::cards{path="kpiSostegno" search="false"}
🤝 **{perc_sostegno}%** posti di sostegno — **{ata}** unità di personale ATA
:::
::::

## L'organico che avrai: la proiezione

Stesso strumento della pagina iscrizioni, applicato ai titolari: il trend
prolungato in avanti, per ragionare su pensionamenti e fabbisogno.

::od-query{into="trendDocenti" sql="SELECT substr(anno_scolastico,1,4)::INTEGER AS anno, sum(totale) AS docenti FROM personale_scuola WHERE provincia = '{#provincia}' AND categoria = 'Docente' GROUP BY 1 ORDER BY 1"}

::range[anniOrg]{min="1" max="5" value="3" legend="Anni di proiezione"}

:::select{id="algoOrg" placeholder="Trend lineare (default)"}
- ARIMA/SARIMA
- Holt-Winters (ETS)
:::

::ml-forecast{data="trendDocenti" x="anno" y="docenti" horizon="#anniOrg" model="#algoOrg" into="trendDocPrev"}

::chart-line{data="trendDocPrev" x="anno" y="docenti,previsione" height="16rem"}

::::grid{cols="2"}
**Per fascia d'età** (l'onda dei pensionamenti si vede qui):

::od-query{into="etaDocenti" sql="SELECT fascia_eta AS fascia, sum(totale) AS docenti FROM personale_scuola WHERE provincia = '{#provincia}' AND categoria = 'Docente' AND anno_scolastico = (SELECT max(anno_scolastico) FROM personale_scuola) GROUP BY fascia_eta ORDER BY min(CASE fascia_eta WHEN 'Fino a 34' THEN 1 WHEN 'Tra 35 e 44' THEN 2 WHEN 'Tra 45 e 54' THEN 3 ELSE 4 END)"}

::chart-bar{data="etaDocenti" x="fascia" y="docenti" height="15rem"}
---
**Per grado di scuola**:

::od-query{into="gradoDocenti" sql="SELECT grado AS grado, sum(totale) AS docenti FROM personale_scuola WHERE provincia = '{#provincia}' AND categoria = 'Docente' AND anno_scolastico = (SELECT max(anno_scolastico) FROM personale_scuola) GROUP BY grado ORDER BY grado"}

::chart-bar{data="gradoDocenti" x="grado" y="docenti" height="15rem"}
::::

Solo personale di RUOLO: il precariato non è nella fonte. Il rapporto
alunni/docente incrocia due dataset (iscrizioni statali senza infanzia ÷
titolari con infanzia): un indicatore di tendenza, non un dato di organico
ufficiale.

:::::

:::::page{title="La mappa" icon="🗺️"}

## L'Italia della scuola, colorata dai dati

**Matematica in 5ª primaria** (punteggio INVALSI, ultimo anno) — passa il
mouse per il valore:

::od-query{into="mappaInvalsi" sql="SELECT r.regione AS regione, r.geojson AS geojson, round(i.punteggio_medio) AS punteggio FROM istat_confini_regioni r JOIN invalsi_regionale i ON i.regione = r.regione WHERE i.grado='5ª primaria' AND i.materia='Matematica' AND i.anno=(SELECT max(anno) FROM invalsi_regionale)" limit="30"}

:::map{path="mappaInvalsi" geojson="geojson" fill="punteggio" height="26rem"}
**{regione}** — punteggio {punteggio}
:::

**Abbandono alle superiori** (tasso %, ultimo biennio) — qui il colore scuro
è il problema:

::od-query{into="mappaDispersione" sql="SELECT r.regione AS regione, r.geojson AS geojson, d.tasso_abbandono_perc AS tasso FROM istat_confini_regioni r JOIN dispersione_scolastica d ON d.regione = r.regione WHERE d.grado='II grado' AND d.anno_frequenza=(SELECT max(anno_frequenza) FROM dispersione_scolastica WHERE regione != 'ITALIA' AND grado='II grado')" limit="30"}

:::map{path="mappaDispersione" geojson="geojson" fill="tasso" height="26rem"}
**{regione}** — abbandono {tasso}%
:::

Le regioni senza colore non hanno il dato nella fonte (Valle d'Aosta e
Trentino-Alto Adige per la dispersione; il Trentino-Alto Adige INVALSI è
pubblicato come due province autonome, non come regione).

:::::

:::::page{title="Esplora" icon="🔍"}

## Il pivot: fai le tue domande trascinando

Le iscrizioni per regione, grado e anno (600 combinazioni): **trascina le
colonne** per raggruppare, cambia tipo di grafico, filtra — come una tabella
pivot, anche in modalità Uso.

::od-query{into="pivotIscrizioni" sql="SELECT regione AS regione, grado AS grado, substr(anno_scolastico,1,4)::INTEGER AS anno, sum(alunni) AS alunni FROM iscrizioni_scolastiche WHERE regione IS NOT NULL AND codice_istat IS NOT NULL GROUP BY 1,2,3 ORDER BY 1,2,3" limit="1000"}

:::explore{path="pivotIscrizioni" view="bar" group-by="regione" columns="alunni" height="30rem"}
:::

## O chiedi a parole

Con un motore AI configurato (menu AI in alto), domande in linguaggio
naturale sugli stessi dati: "quanti alunni ha la Lombardia nel 2024?",
"le 5 regioni che hanno perso più alunni".

::ai-query{data="pivotIscrizioni" into="rispostaAi"}

:::table{path="rispostaAi" pagesize="10"}
{regione} {grado} {anno} {alunni} {valore}
:::

:::::

---

I dati sono ufficiali e aperti: **iscrizioni, edilizia scolastica e
personale** del MIUR — Portale Unico dei Dati della Scuola (Open Data IODL
2.0), **dispersione scolastica** del MIM — Ufficio di Statistica (riuso
libero con citazione, estratta dai PDF ufficiali con parsing a coordinate
del layer di testo, mai da un modello vision), **risultati INVALSI
regionali** di INVALSI — Servizio Statistico (CC BY 4.0 IT), **confini**
ISTAT. Si agganciano da soli tramite comune, regione o provincia. Nessun
dato tuo lascia il dispositivo.