= read.csv("./data/DatiCom.csv") dati
4 Lab 3 - 15/03/2024
In questa lezione vedremo:
- come installare un pacchetto (package o library) aggiuntivo di
R
, in particolaretidyverse
- come utilizzare l’operatore pipe
%>%
- come utilizzare i verbi di
tidyverse
Verranno utilizzati i dati disponibili nel file DatiCom.csv che vengono quindi importati in R
secondo quanto descritto in Section 3.1.
Si tratta di un dataframe con 7900 righe (comuni) e 11 variabili la cui struttura è la seguente:
str(dati)
'data.frame': 7900 obs. of 11 variables:
$ codreg : int 1 1 1 1 1 1 1 1 1 1 ...
$ codcom : int 1001 1002 1003 1004 1006 1007 1008 1009 1010 1011 ...
$ nomecom : chr "Agli\x8f" "Airasca" "Ala di Stura" "Albiano d'Ivrea" ...
$ sup : num 13.2 15.7 46.3 11.7 17.9 ...
$ pop : int 2558 3681 465 1628 6280 251 16497 2012 479 810 ...
$ zona_alt: int 3 5 1 3 3 1 3 3 1 1 ...
$ alt : int 315 257 1080 230 364 957 314 306 836 782 ...
$ lito : int 0 0 0 0 0 0 0 0 0 0 ...
$ isol : int 0 0 0 0 0 0 0 0 0 0 ...
$ cost : int 0 0 0 0 0 0 0 0 0 0 ...
$ urban : int 2 3 3 3 2 3 2 3 3 3 ...
In particolare, la seguente è la definizione delle variabili:
codreg
: codice regione in cui il comune è collocatocodcom
: codice Istat del comunenomecom
: denominazione del comunesup
: superficie del comune in Km quadratipop
: popolazione residente nel comune al 31/12/2022zona_alt
: zona altimetrica del comune (1=Montagna interna; 2=Montagna litoranea; 3=Collina interna; 4=Collina litoranea; 5=Pianura)alt
: altitude sul livello del mare (in metri) in corrispondenza della sede del municipiolito
: comune litoraneo (1=Comune litoraneo, 0=Comune non litoraneo)isol
: comune isolano (1=Comune isolano, 0=Comune non isolano)cost
: zone costiere (1=Zone costiere, comuni situati sulla costa o aventi almeno il 50 % della superficie a una distanza dal mare inferiore a 10 km; 0=Zone non costiere)urban
: grado di urbanizzazione (1=Città o Zone densamente popolate; 2=Piccole città e sobborghi o Zone a densità intermedia di popolazione; 3=Zone rurali o Zone scarsamente popolate)
4.1 Il pacchetto tidyverse
In generale un pacchetto di R
è una collezione di funzioni, dati e documentazione che estende le capacità di R
di base. La lista completa dei pacchetti di R è disponibile al link https://cran.r-project.org/web/packages/available_packages_by_name.html.
tidyverse
è un insieme di pacchetti di R
sviluppati appositamente per la data science (see Figure 4.1) e, in particolare, per manipolare, analizzare e rappresentare graficamente dati. Tutti i pacchetti dentro la collezione tidyverse
condividono la stessa filosofia, struttura dei dati e sintassi del codice. Si veda qui per la pagine web di tidyverse
e qui per il libro R for Data Science - edizione italiana.
tidyverse
Per vedere come installare un pacchetto si veda il paragrafo che segue.
4.2 Installare e caricare un pacchetto
Prima di iniziare ad utilizzare un pacchetto (ovvero le funzioni in esso contenute) è solitamente necessario seguire due passaggi:
- installare il pacchetto: questa procedura deve essere eseguita solamente una volta (a meno che decidiate di reinstallare
R
, di cambiare o resettare il computer). E’ come decidere di comprare una lampadina e di montarla (si veda Figure 4.2): questa azione viene fatta solamente una sola volta e non ogni volta che è necessario avere luce in una stanza.
La procedura di installazione può essere fatta utilizzando il pannello in basso a destra di RStudio, tab Packages, icona “Install” (di fatto tramite il menù di RStudio si sta usando la funzione install.packages("...")
).
- caricare il pacchetto: questa azione corrisponde all’azione di accendere con l’interrutore la luce in una stanza ogni qual volta sia necessario (si veda Figure 4.2). Allo stesso modo, un pacchetto può essere caricato più volte, ogni qual volta sia necessario utilizzare una delle funzioni incluse nel pacchetto.
Siamo ora interessati al pacchetto tidyverse
(che in realtà è un insieme di pacchetto). Una volta che il pacchetto tidyverse
è stato installato e caricato, è possibile utilizzare tutte le funzioni in esso contenute. Il caricamento di un pacchetto si esegue usando la funzione library
:
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
4.3 Operatore pipe
La sintassi di tidyverse
prevede l’uso dell’operatore pipe
(%>%
) che permette di scrivere in maniera molto intuitiva una sequenza di operazioni (vedere qui per più dettagli).
Si consideri una generica funzione di R
denominata f
con un unico argomento x
. Di solito il seguente approccio (classico) viene utilizzato per utilizzare f
:
f(x)
Un alternativa è data dall’operatore pipe %>%
utilizzato con tidyverse
. Funziona come segue, in maniera sequenziale:
%>% f()
x #equivalente a f(x)
Di fatto, il pipe passa x
come primo argomento della funzione f
. La scorciatoia da tastiera che permette di digitare il pipe è CTRL/CMD Shift M (shift è il tasto per il maiuscolo).
Facciamo ora qualche esempio con il pipe utilizzando un vettore di 5 dati:
= c(11, 19, 3, 7, 12)
x
x
[1] 11 19 3 7 12
Siamo ora interessati a calcolare il logaritmo naturale dei numeri in x
. Con l’approccio standard di R
utilizziamo il seguente codice:
log(x)
[1] 2.397895 2.944439 1.098612 1.945910 2.484907
mentre con il pipe
%>%
x log()
[1] 2.397895 2.944439 1.098612 1.945910 2.484907
dove x
è utilzzato come primo argomento della funzione log
. E’ anche possibile specificare un secondo argomento, come ad esempio la base (base
) del logaritmo (ad esempio 5). In questo caso x %>% f(y)
coincide con f(x,y)
.
#approccio standard
log(x, base=5)
[1] 1.4898961 1.8294828 0.6826062 1.2090620 1.5439593
#approccio con pipe
%>%
x log(base=5)
[1] 1.4898961 1.8294828 0.6826062 1.2090620 1.5439593
Vogliamo ora, dopo aver calcolato il logaritmo, arrotondare tutti i numeri a due decimali. Questo richiede l’utilizzo di due funzioni (log
e round
):
# approccio standard
round(log(x, base = 5), digits = 2)
[1] 1.49 1.83 0.68 1.21 1.54
#approccio con pipe
%>%
x log(base = 5)%>%
round(digits = 2)
[1] 1.49 1.83 0.68 1.21 1.54
Aggiungiamo ora un altro passaggio. Dopo aver arrotondiamo i 5 numeri ne facciamo la somma:
# approccio standard
sum(round(log(x, base = 5), digits = 2))
[1] 6.75
# approcci con pipe
%>%
x log(base = 5) %>%
round(digits = 2) %>%
sum
[1] 6.75
Il risultato è uno scalare.
4.4 Prime funzioni (verbi) di tidyverse
Andiamo ora a lavorare con l’oggetto (dataframe) dati
creato precedentemente. In particolare, andremo ad utilizzare le principali funzioni dal pacchetto tidyverse
(usando l’operatore pipe %>%
).
4.4.1 Distribuzione di frequenza con count
Per calcolare la distribuzione di frequenza (si veda anche Section 3.2) si può utilizzare la funzione count
. Ad esempio, per la variabile zona_alt
si procede come segue:
%>%
dati count(zona_alt)
zona_alt n
1 1 2370
2 2 117
3 3 2530
4 4 785
5 5 2098
Viene restituita una tabella con 5 righe (il numero di modalità di zona_alt
) e due colonne: quella con le modalità e quella con le frequenze assolute (si noti il nome n
della seconda colonna, scelto in automatico dalla funzione count
). La moda della distribuzione è la modalità 3 (Collina Interna) in quanto ad essa è associata la frequenza maggiore.
4.4.2 mutate
: per creare nuove variabili
La funzione mutate
permette di creare una nuova colonna/variabile nel dataframe ottenuta come trasformazione di una delle variabili esistenti.
Si voglia ad esempio definire una nuova variabile (denominata altkm
) data dall’altitudine alt
espressa in kilometri anzichè metri. Si procede come segue:
= dati %>%
dati mutate(altkm = alt/1000)
Si noti che utilizzano dati= ...
si va a sovrascrivere il vecchio dataframe. La nuova versione di dati
avrà quindi una nuova colonna:
str(dati)
'data.frame': 7900 obs. of 12 variables:
$ codreg : int 1 1 1 1 1 1 1 1 1 1 ...
$ codcom : int 1001 1002 1003 1004 1006 1007 1008 1009 1010 1011 ...
$ nomecom : chr "Agli\x8f" "Airasca" "Ala di Stura" "Albiano d'Ivrea" ...
$ sup : num 13.2 15.7 46.3 11.7 17.9 ...
$ pop : int 2558 3681 465 1628 6280 251 16497 2012 479 810 ...
$ zona_alt: int 3 5 1 3 3 1 3 3 1 1 ...
$ alt : int 315 257 1080 230 364 957 314 306 836 782 ...
$ lito : int 0 0 0 0 0 0 0 0 0 0 ...
$ isol : int 0 0 0 0 0 0 0 0 0 0 ...
$ cost : int 0 0 0 0 0 0 0 0 0 0 ...
$ urban : int 2 3 3 3 2 3 2 3 3 3 ...
$ altkm : num 0.315 0.257 1.08 0.23 0.364 0.957 0.314 0.306 0.836 0.782 ...
Si ritorni ora alla distribuzione di frequenza calcola precedentemente per zona_alt
:
%>%
dati count(zona_alt)
zona_alt n
1 1 2370
2 2 117
3 3 2530
4 4 785
5 5 2098
e si voglia aggiungere a questa tabella (dataframe) - con mutate
- una nuova colonna data dalle frequenze percentuali (si veda Section 3.2) arrotondate a un decimale:
%>%
dati count(zona_alt) %>%
mutate(perc = n/sum(n)*100) %>%
mutate(perc = round(perc,1))
zona_alt n perc
1 1 2370 30.0
2 2 117 1.5
3 3 2530 32.0
4 4 785 9.9
5 5 2098 26.6
Si noti la possibilità di concatenare più operazioni utilizzando l’operatore %>%
.
4.4.3 select
: per selezionare le variabili
La funzione select
permette di selezionare una o più variabili dal dataframe. Ad esempio il seguente codice:
%>%
dati select(pop) %>%
head()
pop
1 2558
2 3681
3 465
4 1628
5 6280
6 251
seleziona solamente la colonna pop
tra tutte quelle disponibili. L’utilizzo della funzione head()
serve solamente a mostrare le prime 6 righe dell’output (che altrimenti sarebbe composto da quasi 8000 righe). Per selezionare eventualmente più variabili esse vanno specificate separate da virgola. Ad esempio:
%>%
dati select(pop, lito, cost) %>%
head()
pop lito cost
1 2558 0 0
2 3681 0 0
3 465 0 0
4 1628 0 0
5 6280 0 0
6 251 0 0
Se le variabili sono consecutive si può utilizzare il :
, ad esempio:
%>%
dati select(sup:isol) %>% #tutte le variabili da sup a isol
head()
sup pop zona_alt alt lito isol
1 13.15 2558 3 315 0 0
2 15.74 3681 5 257 0 0
3 46.33 465 1 1080 0 0
4 11.73 1628 3 230 0 0
5 17.88 6280 3 364 0 0
6 5.63 251 1 957 0 0
Infine, è anche possibile utilizzare select
con il segno -
per selezionare tutte le variabili tranne alcune. Si voglia ora ad esempio NON selezionare altkm
eliminandola definitivmente dal dataframe dati
:
= dati %>%
dati select(-altkm)
str(dati) #altkm non c'è più
'data.frame': 7900 obs. of 11 variables:
$ codreg : int 1 1 1 1 1 1 1 1 1 1 ...
$ codcom : int 1001 1002 1003 1004 1006 1007 1008 1009 1010 1011 ...
$ nomecom : chr "Agli\x8f" "Airasca" "Ala di Stura" "Albiano d'Ivrea" ...
$ sup : num 13.2 15.7 46.3 11.7 17.9 ...
$ pop : int 2558 3681 465 1628 6280 251 16497 2012 479 810 ...
$ zona_alt: int 3 5 1 3 3 1 3 3 1 1 ...
$ alt : int 315 257 1080 230 364 957 314 306 836 782 ...
$ lito : int 0 0 0 0 0 0 0 0 0 0 ...
$ isol : int 0 0 0 0 0 0 0 0 0 0 ...
$ cost : int 0 0 0 0 0 0 0 0 0 0 ...
$ urban : int 2 3 3 3 2 3 2 3 3 3 ...
4.4.4 case_when
: ricodifica di una variabile
La variabile zona_alt
, come visto precedentemente, assume come categorie i valori interi da 1 a 5. Come specificato all’inizio di questa lezione, in realtà questa è una variabile qualitativa con le seguenti modalità: 1=Montagna interna; 2=Montagna litoranea; 3=Collina interna; 4=Collina litoranea; 5=Pianura. Procediamo quindi ora alla ricodifica di zona_alt
usando la funzione mutate
(creiamo una nuova variabile zona_alt2
) abbinata a case_when
. Si procede come segue:
= dati %>%
dati mutate(zona_alt2 = case_when(
== 1 ~ "Montagna interna",
zona_alt == 2 ~ "Montagna lit.",
zona_alt == 3 ~ "Collina interna",
zona_alt == 4 ~ "Collina lit.",
zona_alt == 5 ~ "Pianura"
zona_alt ))
Alla sinistra della tilde ~
vengono specificate le categorie numeriche della variabile zona_alt
(attenzione il simbolo ==
significa “esattamente uguale a”), mentre a destra della tilde le nuove categorie (stringhe di testo tra virgolette) della nuova variabile zona_alt2
. Per verificare che tutto sia corretto possiamo calcolare la nuova distribuzione di frequenza:
%>%
dati count(zona_alt2)
zona_alt2 n
1 Collina interna 2530
2 Collina lit. 785
3 Montagna interna 2370
4 Montagna lit. 117
5 Pianura 2098
4.4.5 summarise
: per calcolare le statistiche descrittive
La funzione di tidyverse
denominata summarise
ci permette di calcolare delle statistiche descrittive per ciascuna colonna (variabile). Ad esempio il seguente codice calcola la media e la mediana dell’altitudine si procede come segue:
%>%
dati summarise(mean(alt), median(alt))
mean(alt) median(alt)
1 354.6885 289
E’ possibile anche calcolare statistiche descrittive condizionatamente alle categorie di una variabile qualitativa come zona_alt2
:
%>%
dati group_by(zona_alt2) %>%
summarise(mean(alt), median(alt))
# A tibble: 5 × 3
zona_alt2 `mean(alt)` `median(alt)`
<chr> <dbl> <dbl>
1 Collina interna 339. 318
2 Collina lit. 205. 180
3 Montagna interna 653. 638.
4 Montagna lit. 298. 300
5 Pianura 96.1 74
Come ci si aspetta, l’altitudine media (e mediana) per i comuni di montagna interna (653 metri) è maggiore dell’altitudine media dei comuni di pianura (96.1 metri).
4.5 Esercizi Lab 3
4.5.1 Esercizio 1
Si consideri nuovamente il dataframe dati
relativo ai dati dei comuni italiani, già considerato per il Lab 3. Caricare la libreria tidyverse
.
Creare una nuova variabile denominata
dens
che rappresenta la densità di popolazione. Essa è data dal rapporto tra la popolazione residente e la superficie del comune.Creare una nuova variabile
urban2
andando a ricodificare la variabileurban
secondo le seguenti categorie: 1=Zone densamente popolate; 2=Zone a densità intermedia; 3=Zone scarsamente popolate.Ricavare la distribuzione di frequenza della variabile
urban2
usando anche le frequenze percentuali. Quale è la moda della distribuzione?Calcolare la densità di popolazione media dei comuni italiani usando
dens
. Commentare.Calcolare la densità di popolazione media dei comuni italiani usando
dens
, condizionatamente alle categorie diurban2
. Commentare.Creare un nuovo dataframe
smalldati
che contiene solamente le colonnecodcom
,sup
epop
.