Esercitazione 01 - Il sistema bibliotecario cittadino
Lavoro di gruppo in aula
Introduzione
Il Comune ha chiesto al vostro gruppo di analizzare i dati del 2025 del sistema bibliotecario cittadino, composto da quattro biblioteche. I dati (fittizi) provengono da fonti diverse, sono in formati diversi e, come spesso accade con i dati reali, contengono alcune imprecisioni.
L’esercitazione si svolge in due fasi:
- una parte comune, uguale per tutti i gruppi, in cui importerete, pulirete e unirete le tabelle dei dati
- una missione, diversa per ogni gruppo, in cui risponderete ad alcune domande concrete sui dati
Al termine ogni gruppo presenterà alla classe i risultati della propria missione.
Obiettivi di apprendimento
Lo svolgimento dell’esercitazione vi permetterà di:
- ripercorrere in un’unica analisi tutte le fasi viste finora: importazione, pulizia, codifica e incrocio delle tabelle
- usare i verbi di
dplyrper rispondere a domande concrete, compresiselect,filter,group_byesummarise - scegliere la tabella e il tipo di join adatti alla domanda
- spiegare ad altri il proprio codice e i propri risultati
Organizzazione
Lavorate in gruppi di 2 o 3 persone, con un solo computer su cui scrivere lo script. Alternatevi alla tastiera: chi non scrive consulta l’help, controlla i risultati e propone le soluzioni.
Avete a disposizione circa un’ora: indicativamente 20 minuti per la parte comune e 40 minuti per la missione. Se la parte comune vi richiede più tempo, non preoccupatevi: nella missione affrontate per primi i punti obbligatori.
Create un progetto RStudio di nome
es01con una sottocartelladati, in cui salvare i cinque file dei dati che trovate su Teams.Scrivete le risposte in un unico script
es01_gruppoN.R, doveNè il numero del vostro gruppo. Inserite all’inizio i nomi dei componenti del gruppo e usate un’etichetta di sezione per ogni punto (ad esempio# COMUNE 3 ----oppure# MISSIONE B2 ----).Commentate brevemente ogni risultato: la risposta alla domanda e, quando è il caso, le difficoltà incontrate.
Potete consultare l’help, i materiali del corso e un assistente AI, ma ogni istruzione presente nello script deve essere compresa dal gruppo e spiegabile durante la presentazione.
Al termine, uno dei componenti carica lo script su Teams per tutto il gruppo.
I dati
I file da salvare nella cartella dati sono i seguenti.
utenti.csv: anagrafe degli iscritti al sistema bibliotecario (una riga per utente, campi separati da ;)
| Colonna | Contenuto |
|---|---|
ID Utente |
codice dell’utente |
Genere |
F o M |
Anno di nascita |
anno di nascita |
Categoria |
STU studente, LAV lavoratore, PEN pensionato, DOC docente, ALT altro |
Biblioteca di iscrizione |
codice della biblioteca presso cui l’utente si è iscritto |
Anno iscrizione |
anno di iscrizione |
prestiti.xlsx: due fogli. Il foglio Prestiti 2025 contiene il registro dei prestiti (una riga per prestito); il foglio Biblioteche le informazioni sulle quattro biblioteche
Colonna (foglio Prestiti 2025) |
Contenuto |
|---|---|
N. prestito |
numero progressivo del prestito |
Cod. utente |
codice dell’utente |
Inventario |
codice di inventario del libro |
Biblioteca |
codice della biblioteca in cui è avvenuto il prestito |
Data prestito |
data del prestito |
Data restituzione |
data della restituzione (vuota se il libro non è stato ancora restituito) |
Proroga |
SI se il prestito è stato prorogato, NO altrimenti |
Colonna (foglio Biblioteche) |
Contenuto |
|---|---|
Codice |
codice della biblioteca |
Nome |
nome della biblioteca |
Quartiere |
quartiere in cui si trova |
Ore apertura settimanali |
ore di apertura al pubblico in una settimana |
Posti a sedere |
posti a sedere nelle sale di lettura |
catalogo.txt: catalogo dei libri (una riga per libro, campi separati da tabulazione)
| Colonna | Contenuto |
|---|---|
Inventario |
codice di inventario del libro |
Titolo, Autore |
titolo e autore |
Genere |
genere letterario: Narrativa, Saggistica, Poesia, Ragazzi, Fumetti |
Anno pubblicazione |
anno della prima pubblicazione dell’opera |
gruppo_lettura.csv e laboratorio_scrittura.csv: codici degli utenti iscritti alle due attività culturali organizzate nel 2025 (una sola colonna, ID utente)
Un prestito dura 30 giorni; con la proroga la durata sale a 60 giorni. I dati sono aggiornati al 31 dicembre 2025. Nel mese di agosto le biblioteche chiudono per la pausa estiva.
Parte comune (tutti i gruppi)
Carica i package
tidyverse,readxlejanitorImporta i cinque file (e i due fogli del file Excel) in sei tabelle chiamate
utenti,prestiti,biblioteche,catalogo,gruppo_letturaelaboratorio_scrittura, pulendo sempre i nomi delle colonne conclean_names. Stampa a video le dimensioni di ciascuna tabella
- Prima di importare un file, osservatelo: quale separatore usa? Ci sono righe da saltare prima dell’intestazione?
- Per i file di testo potete usare
read_delim(indicando il separatore),read_csvoread_tsv; per il file Excelread_excel, indicando il foglio con l’argomentosheet.
Controlla i valori distinti delle colonne
categoriaegenerediutentie correggi i problemi di codifica che trovi. Poi, con un’unica chiamata dimutate:- ricodifica la categoria con le etichette estese (
Studente,Lavoratore,Pensionato,Docente,Altro) - trasforma il genere in un factor con etichette
FemminaeMaschio - aggiungi una colonna
etacon l’età degli utenti nel 2025
- ricodifica la categoria con le etichette estese (
Ricorda le differenze tra le due funzioni:
replace_valuessostituisce solo i valori indicati e lascia invariati gli altri; il risultato ha sempre lo stesso tipo del vettore di partenza, per cui i nuovi valori devono essere compatibili con esso (replace_values(c(1, 2), 1 ~ "si")restituisce un errore)recode_valuescostruisce un vettore nuovo: i valori non previsti diventanoNAe il tipo del risultato dipende dai nuovi valori, per cui permette ad esempio di passare da codici numerici a etichette testuali
Sia
utentisiacatalogocontengono una colonna chiamatagenere, ma con un significato diverso. Cosa accadrebbe unendo le due tabelle in un’unica tabella? Rinomina la colonna dicatalogoingenere_letterarioCostruisci la tabella
prestiti_completoche contenga, per ogni prestito effettuato da un utente presente in anagrafe, le informazioni sull’utente e sul libro. Confronta il numero di righe diprestitie diprestiti_completoe conta le righe diprestiti_completosenza titolo del libro: cosa è successo?
Verificate che prestiti_completo abbia lo stesso numero di righe ottenuto dagli altri gruppi: se ci sono differenze, confrontatevi prima di procedere.
Le missioni
Ogni gruppo svolge una sola missione, assegnata dal docente. I punti contrassegnati da ★ sono facoltativi: affrontateli solo se vi resta tempo.
filter(tabella, condizione)conserva solo le righe che soddisfano la condizioneselect(tabella, colonne)conserva solo le colonne indicategroup_by(tabella, colonne)raggruppa le righe secondo i valori delle colonne indicate; i verbi successivi lavorano gruppo per grupposummarise(tabella, nome = funzione(colonna))calcola una sintesi (per ogni gruppo, se la tabella è raggruppata); all’interno disummarise,n()restituisce il numero di righe del gruppo en_distinct(colonna)il numero di valori distintiarrange(tabella, desc(colonna))ordina le righe in senso decrescente;head(tabella, 10)restituisce le prime 10 righex %in% yrestituisceTRUEper gli elementi dixpresenti nel vettorey
Missione A: Chi sono i lettori?
L’assessorato alla cultura vuole sapere quali gruppi di cittadini usano di più le biblioteche.
A1. Quanti utenti appartengono a ciascuna categoria? Ordina il risultato dalla categoria più numerosa alla meno numerosa
A2. Aggiungi a utenti una colonna classe_eta con le classi meno di 18, 18-29, 30-49, 50-64, 65 e oltre, trasformata in un ordered factor. Quanti utenti ci sono in ciascuna classe? Cosa accade agli utenti di cui non è noto l’anno di nascita?
A3. Calcola il numero di prestiti di ciascun utente e aggiungilo alla tabella utenti, in modo che anche gli utenti senza prestiti compaiano con il valore 0. Quanti sono gli utenti che nel 2025 non hanno preso in prestito nessun libro?
Partite da prestiti_completo e usate group_by e summarise per ottenere una tabella con una riga per utente; poi unitela a utenti con il join adatto. Quale valore assumono gli utenti senza prestiti dopo il join? Come potete trasformarlo in 0?
A4. Per ciascuna categoria calcola il numero di utenti, il numero medio di prestiti per utente e la quota di utenti che hanno preso in prestito almeno un libro. Quale categoria legge di più? Ripeti il calcolo per classe di età
A5. ★ Calcola il numero medio di prestiti per utente in due modi: su tutti gli utenti e solo sugli utenti con almeno un prestito. Quale dei due valori è corretto per rispondere alla domanda “quanti libri prende in prestito in media un iscritto”?
Per la discussione: quale tipo di join avete usato al punto A3, e cosa sarebbe cambiato nei risultati del punto A4 usando un inner_join?
Missione B: Le biblioteche
Il Comune deve decidere come distribuire tra le quattro biblioteche le risorse del prossimo anno e vuole confrontarne l’attività.
B1. Per ciascuna biblioteca calcola il numero di prestiti e il numero di utenti distinti che vi hanno preso libri in prestito. Quale tabella è più corretto usare, prestiti o prestiti_completo? Perché?
B2. Aggiungi al risultato del punto B1 il nome e le ore di apertura settimanali di ciascuna biblioteca e calcola il numero di prestiti per ora di apertura. Ordina le biblioteche dalla più “produttiva” alla meno produttiva, con la colonna del nome subito dopo quella del codice
B3. Gli utenti prendono libri in prestito soprattutto nella biblioteca in cui si sono iscritti? Per ciascuna biblioteca calcola la quota di prestiti effettuati da utenti iscritti in quella stessa biblioteca
Il confronto biblioteca == biblioteca_di_iscrizione restituisce un valore logico per ogni prestito: cosa rappresenta la sua media?
B4. Calcola il numero di prestiti per mese. In quale mese i prestiti sono stati meno numerosi, e perché?
La funzione month del package lubridate (caricato con il tidyverse) estrae il mese da una data.
B5. ★ Ripeti il conteggio del punto B4 separatamente per ciascuna biblioteca. Ci sono biblioteche con un andamento diverso dalle altre?
Per la discussione: quale biblioteca è la più attiva? La risposta cambia a seconda dell’indicatore usato (prestiti, utenti, prestiti per ora di apertura)?
Missione C: Restituzioni e ritardi
Il servizio prestiti vuole capire quanto spesso i libri vengono restituiti in ritardo.
C1. Aggiungi a prestiti_completo una colonna durata con il numero di giorni trascorsi tra il prestito e la restituzione. Calcola la durata media e mediana dei prestiti, separatamente per i prestiti con e senza proroga
La differenza tra due date si calcola con la funzione difftime; per ottenere un numero di giorni usate as.numeric(difftime(data_fine, data_inizio, units = "days")).
C2. Quanti prestiti non risultano ancora restituiti al 31 dicembre 2025? Come si distribuiscono tra le biblioteche?
C3. Classifica ogni prestito in una delle seguenti situazioni, in una nuova colonna stato: restituito in tempo, restituito in ritardo, non restituito, in ritardo (il termine è già scaduto al 31 dicembre 2025), in corso (il termine non è ancora scaduto). Quanti prestiti ricadono in ciascuna situazione?
Create prima una colonna con il limite di durata del prestito (30 o 60 giorni) usando if_else. Per i prestiti non restituiti, i giorni trascorsi si calcolano rispetto alla data as.POSIXct("2025-12-31", tz = "UTC"). Ricordate che case_when usa la prima condizione vera.
C4. Calcola per ciascuna categoria di utenti la quota di prestiti in ritardo (restituiti in ritardo o non restituiti con termine scaduto). Quale categoria è la meno puntuale?
C5. ★ Esegui mean(prestiti_completo$durata) e commenta il risultato. Come va corretto il calcolo? Quali prestiti vengono esclusi dalla media corretta?
Per la discussione: la durata media calcolata sui soli prestiti restituiti rischia di sottostimare la durata reale dei prestiti. Perché?
Missione D: Cosa si legge?
La commissione acquisti vuole orientare l’acquisto dei nuovi libri.
D1. Quali sono i 10 libri più prestati nel 2025? Riporta titolo, autore e numero di prestiti. Cosa rappresenta l’eventuale riga senza titolo, e come potete escluderla?
D2. Per ciascuna categoria di utenti calcola il numero di prestiti di ciascun genere letterario e la quota di ciascun genere sul totale dei prestiti della categoria. Quali sono le differenze più evidenti tra le categorie?
Dopo group_by(categoria, genere_letterario) e summarise, la tabella resta raggruppata per categoria (R lo segnala con un messaggio): una successiva mutate(quota = n / sum(n)) calcola quindi la somma all’interno di ciascuna categoria.
D3. Quali libri del catalogo non sono mai stati presi in prestito nel 2025?
D4. Aggiungi al catalogo una colonna epoca che classifichi gli anni di pubblicazione in prima del 1900, 1900-1945, 1946-1999, dal 2000. Per ciascuna epoca calcola il numero di titoli presenti in catalogo e il numero di prestiti. I libri più recenti sono più richiesti? Per rispondere, rapportate i prestiti al numero di titoli
D5. ★ Chi sono gli autori più prestati? Il risultato è diverso dalla classifica dei libri del punto D1?
Per la discussione: per confrontare la popolarità delle epoche, perché non basta confrontare il numero di prestiti?
Missione E: Qualità dei dati e attività culturali
Il responsabile del sistema informativo vuole verificare la qualità dei dati; l’ufficio eventi vuole sapere chi partecipa alle attività culturali.
E1. Quali prestiti del registro riguardano utenti che non compaiono nell’anagrafe? Quali riguardano libri che non compaiono nel catalogo? Osservando i codici, formulate un’ipotesi sull’origine di questi casi
E2. Quanti iscritti non hanno preso in prestito nessun libro nel 2025? Come si distribuiscono per categoria?
E3. Usando le operazioni su insiemi, rispondi alle seguenti domande:
- quanti utenti partecipano a entrambe le attività?
- quanti partecipano ad almeno una attività?
- quanti partecipano a una sola attività?
- quanti partecipano solo al gruppo di lettura?
E4. Descrivi i partecipanti alle due attività: come si distribuiscono per categoria gli iscritti al gruppo di lettura e quelli al laboratorio di scrittura?
E5. ★ I partecipanti alle attività culturali prendono in prestito più libri degli altri utenti? Confronta il numero medio di prestiti per utente tra partecipanti e non partecipanti (attenzione agli utenti senza prestiti!)
Per la discussione: nella parte comune, quanti prestiti sono stati esclusi da prestiti_completo e perché? In quali missioni questa esclusione è corretta, e in quali invece potrebbe portare a risultati sbagliati?
La presentazione
Ogni gruppo ha a disposizione 5 minuti, mostrando lo script in RStudio. Organizzate la presentazione così:
- La domanda e la risposta: qual era la vostra missione e cosa avete scoperto? Partite dai risultati, non dal codice
- Il codice: mostrate e spiegate uno o due passaggi chiave (ad esempio un join o una sintesi per gruppi)
- Una difficoltà: un errore o un risultato inatteso che avete incontrato, e come lo avete risolto (o perché non ci siete riusciti)
- La domanda per la discussione: la vostra risposta, da discutere con la classe
Non è necessario aver completato tutti i punti: un errore spiegato bene è utile alla discussione quanto un risultato corretto.