5  Lab 4 - 22/03/2024

In questa lezione vedremo:

Verranno nuovamente utilizzati i dati disponibili nel file DatiCom.csv già in uso nel Chapter 4.

dati = read.csv("./data/DatiCom.csv")

Come prima cosa è necessario caricare il pacchetto tidyverse (come descritto in Section 4.2):

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.2     ✔ tidyr     1.3.0
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

5.1 Rappresentazioni grafiche tramite ggplot

All’interno della collezione tidyverse è disponibile il pacchetto ggplot (Grammar of Graphics) che permette di ottenere rappresentazioni grafiche (https://ggplot2.tidyverse.org/). Come si vede in Figure 5.1 ggplot costruisce il grafico tramite una serie di layer. Il primo livello specifica il sistema di coordinate; successivamente vengono aggiunti gli altri layer caratterizzata da una specifica geometria (geom_...) e caratteristiche estetiche (aes(...)).

Figure 5.1: La struttura a layer dei grafici di ggplot

Ogni costruzione di grafico avrà la seguente struttura:

dati %>% 
ggplot() +
  geom_...(aes(…))

ggplot è la funzione che crea il sistema di coordinate. La funzione geom_... è quella che definisce la geometria da rappresentare graficamente (vedere https://ggplot2.tidyverse.org/reference/ per l’elenco di tutte le geometrie disponibili). Infine, aes definisce tutto quello che è importante per l’estetica del grafico (incluse le variabili da rappresentare).

Importante: si noti che dopo ggplot non si utilizza più il pipe (%>%) ma il segno di +.

5.1.1 Geometria geom_bar

Si consideri la variabile zona_alt (eventualmente ricodificata in zona_alt2 come descritto in Section 4.4.4) e se ne ricavi nuovamente la distribuzione di frequenza (si veda anche Section 4.4.1):

dati %>% 
  count(zona_alt)
  zona_alt    n
1        1 2370
2        2  117
3        3 2530
4        4  785
5        5 2098

Rappresentiamo ora graficamente questa distribuzione di frequenza con un grafico a barre che riporta sull’asse delle x le categorie della variabile e sull’asse delle coordinate le corrispondenti frequenze assolute. Questo tipo di grafico può essere utilizzato per una variabile qualitativa o quantitativa che assume un numero finito di valori. Si utilizza il codice che segue usando la geometria geom_bar:

dati %>% 
  ggplot()+
  geom_bar(aes(zona_alt))

In automatico il grafico riporta sull’asse delle y la variabile count che rappresenta la frequenza assoluta, ovvero il numero di comuni per ognuna delle 5 categorie di zona_alt. E’ possibile cambiare i colori esterni (col) e interni (fill) di ogni barra come segue (usando le opzioni col e fill:

dati %>% 
  ggplot()+
  geom_bar(aes(zona_alt), col="blue", fill="orange")

# dentro aes si specifica solo la variabile x

Per cambiare le etichette dei due assi si utilizzano le funzioni xlab e ylab come segue (vengono anche usati colori diversi):

dati %>% 
  ggplot() +
  geom_bar(aes(zona_alt), col = "darkgreen", fill = "#FF9999") +
  xlab("Zona altimetrica") +
  ylab("Frequenze assolute")

5.1.2 Geometria geom_col

Si voglia ora rappresentare sull’asse delle y non le frequenze assolute (come fatto in automatico da geom_bar) ma le frequenze percentuali (si veda Section 3.2). In questo caso è necessario utilizzare la geometrica geom_col che permette di specificare cosa si vuole rappresentare sull’asse delle y. I dati di input del grafico non sarà il dataframe originale dati ma la seguente tabella di distribuzioni di frequenza con le distribuzioni percentuali denominate perc:

dati %>% 
  count(zona_alt) %>% 
  mutate(perc = n/sum(n)*100) 
  zona_alt    n      perc
1        1 2370 30.000000
2        2  117  1.481013
3        3 2530 32.025316
4        4  785  9.936709
5        5 2098 26.556962

Per il grafico si procede come segue:

dati %>% 
  count(zona_alt) %>% 
  mutate(perc = n/sum(n)*100) %>% 
  ggplot() +
  geom_col(aes(zona_alt, perc))

Quello che cambia è la scala dell’asse delle y. Si voglia ora migliorare il grafico andando a mettere un bordo rosso alle colonne e un riempimento di colore dato dai valori delle percentuali (variabile perc). In questo caso l’opzione col andrà specificata dentro aes() (e senza mettere il colore scelto nelle virgolette; il colore è definito dalla variabile perc) come segue:

dati %>% 
  count(zona_alt) %>% 
  mutate(perc = n/sum(n)*100) %>% 
  ggplot() +
  geom_col(aes(zona_alt, perc, fill=perc), 
           col = "red") +
  xlab("Zona altimetrica") +
  ylab("Frequenze percentuali")

Si noti la creazione automatica della legenda con paletta da blu scuro (valori percentuali bassi) a blu chiaro (valori percentuali alti). E’ possibile cambiare la palette di colori come segue (si veda anche https://ggplot2.tidyverse.org/reference/scale_colour_continuous.html):

dati %>% 
  count(zona_alt) %>% 
  mutate(perc = n/sum(n)*100) %>% 
  ggplot() +
  geom_col(aes(zona_alt, perc, fill = perc), col = "red") +
  scale_fill_continuous(type = "viridis") +
  xlab("Zona altimetrica") +
  ylab("Frequenze percentuali")

5.2 Verbo filter

Il verbo filter viene utilizzato per selezionare righe (osservazioni) da un dataframe (andando a stabiliare una condizione per la selezione).

Si voglia ad esempio selezionare solamente i comuni in Lombardia (codreg == 3) e creare un nuovo dataframe di nome datilomb:

datilomb = dati %>% 
  filter(codreg == 3) #esattamente uguale
nrow(datilomb)
[1] 1503

Si noti che in Lombardia sono presenti 1503 comuni. Le variabili (colonne) sono le stesse di dati.

Si voglia ora selezionare solo il comune di Bergamo dentro datilomb:

datilomb %>% 
  filter(nomecom == "Bergamo") 
  codreg codcom nomecom   sup    pop zona_alt alt lito isol cost urban
1      3  16024 Bergamo 40.15 119534        3 249    0    0    0     1

5.2.1 Calcolo indici descrittivi

A partire da datilomb si calcoli per la variabile pop il minimo, il massimo, la media, la varianza e il coefficiente di variazone.

  1. Metodo classico
min(datilomb$pop) #n. persone residenti nel comune con meno abitanti
[1] 32
max(datilomb$pop) #n. persone residenti nel comune con più abitanti (Milano)
[1] 1354196
mean(datilomb$pop) #n. medio di persone residenti nei comuni lombardi
[1] 6620.587
var(datilomb$pop) #variabilità della variabile pop: quanto sono diversi i comuni di lombardia in termini di popolazione?
[1] 1325944151
#CV
sd(datilomb$pop)/mean(datilomb$pop)
[1] 5.500044
  1. Metodo tidyverse
datilomb %>% 
  summarise(min(pop), max(pop), mean(pop), var(pop), sd(pop)/mean(pop))
  min(pop) max(pop) mean(pop)   var(pop) sd(pop)/mean(pop)
1       32  1354196  6620.587 1325944151          5.500044

Se si è interessati a capire quale è il comune con la popolazione minima (32 persone) si usi filter:

datilomb %>% 
  filter(pop == 32)
  codreg codcom   nomecom   sup pop zona_alt  alt lito isol cost urban
1      3  97055 Morterone 13.71  32        1 1070    0    0    0     3

Il codice

datilomb %>% 
  filter(pop < 50)
  codreg codcom          nomecom   sup pop zona_alt  alt lito isol cost urban
1      3  14047         Pedesina  6.30  37        1 1032    0    0    0     3
2      3  18125 Rocca de' Giorgi 10.50  49        3  219    0    0    0     3
3      3  97055        Morterone 13.71  32        1 1070    0    0    0     3

ci dice quale sono i comuni in Lombardia con un numero di abitanti minore di 50.

5.3 Geometria geom_histogram

Volendo rappresentare graficamente una variabile quantitativa continuo o discreta con un numero elevato di categorie, come ad esempio la popolazione, si utilizza l’istogramma (geometria geom_histogram):

datilomb %>% 
  ggplot() +
  geom_histogram(aes(pop))
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

L’istogramma riporta sull’asse delle x i valori della popolazione in classi (definite in automatico da R) e sull’asse delle y le corrispondente frequenze (i.e. numero di comuni lombardi). Sull’asse delle ordinate viene infatti riportato il conteggio (count), ovvero quante osservazioni ci sono per ogni classe di popolazione. In automatico il numero di classi (bins) per i prezzi sono fissate pari a 30. E’ comunque possibile scegliere il numero di classi con l’opzione bins=.... Si noti che molti comuni hanno una popolazione ridotta (nella prima classe di valori), il comune di Milano è quello che si vede nella parte di destra del codice.

Essendo Milano un’anomalia lo si vuole escludere (con filter applicato alla variable nomecom) prima di fare il grafico:

datilomb %>% 
  filter(nomecom != "Milano") %>%  
  ggplot() +
  geom_histogram(aes(pop), col="darkblue") +
  xlab("Popolazione residente (in classi)") +
  ylab("Frequenze assolute")
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Il simbolo != significa diverso da. SI vede che ora l’asse delle x arriva a 200000. Ancora la maggior parte dei comuni è collocata nella parte di destra del grafico.

5.3.1 facet_wrap

Vogliamo ora creare istogrammi per la variabile popolazione separati a seconda delle categorie della zona altimetrica (zona_alt). Si può includere questa informazione settando l’opzione fill con zon_alt trasformato in factor dentro l’aes (vedremo meglio più avanti la questione dei factor):

datilomb %>% 
  filter(nomecom != "Milano") %>%  
  ggplot() +
  geom_histogram(aes(pop, fill = factor(zona_alt)), col="darkblue") +
  xlab("Popolazione residente (in classi)") +
  ylab("Frequenze assolute")
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

In questo caso i 3 istogrammi sono sovrapposti (con colori diversi) e poco leggibili. Sarebbe meglio separare i 3 istogrammi in 3 sotto-grafici diversi. E’ possibile farlo usando la funzione facet_wrap: avere

datilomb %>% 
  filter(nomecom != "Milano") %>%  
  ggplot() +
  geom_histogram(aes(pop, fill = factor(zona_alt)), col="darkblue") +
  facet_wrap(~ zona_alt) +
  xlab("Popolazione residente (in classi)") +
  ylab("Frequenze assolute") 
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Tutte le distribuzioni sono asimmetriche con la maggior parte dei comuni collocata nella parte sinistra delle distribuzioni. In particolare la distribuzione rossa (montagna interna) è quella che ha la prima barra più elevata (classe di popolazione con valori più piccoli), mentre la distribuzione blu (pianura) è quella con la “coda a destra” più lunga, ovvero con più comuni nelle classi di popolazioni con valori maggiori. Si ricordi che è possibile calcolare le statistiche descrittive per la variabile popolazione condizionatamente a zona_alt:

datilomb %>% 
  group_by(zona_alt) %>% 
  summarise(min(pop), max(pop), mean(pop), var(pop), sd(pop)/mean(pop))
# A tibble: 3 × 6
  zona_alt `min(pop)` `max(pop)` `mean(pop)`  `var(pop)` `sd(pop)/mean(pop)`
     <int>      <int>      <int>       <dbl>       <dbl>               <dbl>
1        1         32      46871       2228.   11681823.                1.53
2        3         49     196446       6605.  218002882.                2.24
3        5         59    1354196       9329. 2584152084.                5.45

Il fatto che in pianura viva mediamente più gente conferma i grafici visti sopra. Inoltre, la distribuzione della poplazione in pianura presenta maggiore variabilità (CV=5.45).

5.4 Esercizi Lab 4

5.4.1 Esercizio 1

Si consideri nuovamente il dataframe dati relativo ai dati dei comuni italiani, già considerato per il Lab 3 e 4. Caricare la libreria tidyverse.

  1. Creare la variabile urban2 come ricodificare della variabile urban usando le categorie 1=“densamente pop”, 2=“mediamente pop”, 3=“scarsamente pop”. Costruire la distribuzione di frequenza di urban2. Quale è la moda di urban2?

  2. Rappresentare graficamente la variabile urban2. Usare il colore marrone per il bordo e l’arancio per il riempimento.

  3. Selezionare solo i comuni nella regione Piemonte (codreg uguale a 1) creando un nuovo dataframe denominato datipiem. Quanti comuni ci sono in Piemonte?

  4. Quanti comuni densamente popolati ci sono in Piemonte? Quali sono?

  5. Considerando i dati piemontesi, si voglia ora studiare l’altitudine sul livello del mare (alt). Quale è l’altitudine maggiore? A quale comune corrisponde? E quella minore? E quella media?

  6. Rappresentare graficamente l’altitudine dei comuni piemontesi usando l’istogramma. La distribuzione è simmetrica?

  7. Modificare l’istogramma in modo da avere sottografici a seconda delle categorie di urban2.

  8. Calcolare l’altitudine minima, media, massima, la varianza e il coefficiente di variazione condizionatamente a urban2. Commentare.