1 I dati e la popolazione

1.1 Concetti fondamentali

L’analisi esplorativa dei dati (AED, o Exploratory Data Analysis – EDA) ha lo scopo di mettere in luce aspetti interessanti e pattern caratteristici di un insieme di dati, ricorrendo a riassunti numerici e rappresentazioni grafiche, senza ricorrere a ipotesi formali sui dati.

Alcuni concetti chiave:

  • Popolazione: l’insieme di tutti gli elementi di interesse (finita o infinita).
  • Unità statistica: il singolo elemento della popolazione su cui si osservano le variabili.
  • Variabile (o carattere): ogni aspetto elementare misurato/osservato su ciascuna unità.

Esempio: se la popolazione sono i 218 comuni del Friuli Venezia Giulia, ogni comune è un’unità statistica, e variabili come numero di abitanti o superficie sono caratteri rilevati su di essi.

1.2 Tipi di raccolta dati

I dati possono essere raccolti per scopi diversi:

  • Ricerca scientifica: si usano disegni sperimentali (controllati o osservazionali) che devono rispettare protocolli precisi per permettere la generalizzazione dei risultati.
  • Scopi amministrativi/gestionali: dati prodotti come “effetto collaterale” della gestione di un processo (es. transazioni bancarie, navigazione web).

2 Tipi di variabili statistiche

2.1 Schema generale

Le variabili si classificano in:

Variabile
├── Qualitativa (categoriale)
│   ├── Sconnessa (nominale): es. mezzo di trasporto
│       └── Dicotomica: solo 2 modalità (es. sì/no)
│   └── Ordinale: es. titolo di studio
└── Quantitativa (numerica)
    ├── Discreta: es. numero di figli
    └── Continua: es. peso, reddito

Nota in R: le variabili qualitative vengono gestite come fattori (factor). È importante trasformarle esplicitamente, perché molte funzioni R si comportano diversamente a seconda del tipo.

2.2 Esempi pratici con il dataset AutoBi

Il dataset AutoBi (package insuranceData) contiene dati su sinistri automobilistici. Carichiamolo e ispezioniamone la struttura.

# install.packages("insuranceData")  # eseguire se non installato
library(insuranceData)
data("AutoBi")
str(AutoBi)
#> 'data.frame':    1340 obs. of  8 variables:
#>  $ CASENUM : int  5 13 66 71 96 97 120 136 152 155 ...
#>  $ ATTORNEY: int  1 2 2 1 2 1 1 1 2 2 ...
#>  $ CLMSEX  : int  1 2 1 1 1 2 1 2 2 1 ...
#>  $ MARITAL : int  NA 2 2 1 4 1 2 2 2 2 ...
#>  $ CLMINSUR: int  2 1 2 2 2 2 2 2 2 2 ...
#>  $ SEATBELT: int  1 1 1 2 1 1 1 1 1 1 ...
#>  $ CLMAGE  : int  50 28 5 32 30 35 19 34 61 NA ...
#>  $ LOSS    : num  34.94 10.892 0.33 11.037 0.138 ...
head(AutoBi)
#>   CASENUM ATTORNEY CLMSEX MARITAL CLMINSUR SEATBELT CLMAGE   LOSS
#> 1       5        1      1      NA        2        1     50 34.940
#> 2      13        2      2       2        1        1     28 10.892
#> 3      66        2      1       2        2        1      5  0.330
#> 4      71        1      1       1        2        2     32 11.037
#> 5      96        2      1       4        2        1     30  0.138
#> 6      97        1      2       1        2        1     35  0.309

Le variabili presenti sono:

Variabile Descrizione Tipo teorico
CASENUM Numero del caso Identificativo
ATTORNEY Rappresentato da avvocato (1=sì, 2=no) Qualitativa sconnessa
CLMSEX Sesso del richiedente (1=M, 2=F) Qualitativa sconnessa
MARITAL Stato civile (1=married, …, 4=divorced) Qualitativa sconnessa
CLMINSUR Richiedente assicurato? Qualitativa sconnessa
SEATBELT Cintura di sicurezza allacciata? Qualitativa sconnessa
CLMAGE Età del richiedente Quantitativa discreta/continua
LOSS Ammontare del danno (migliaia $) Quantitativa continua

3 La matrice dei dati e il data frame in R

In R, la matrice dei dati è rappresentata da un data frame:

  • ogni riga = un’unità statistica
  • ogni colonna = una variabile
# Esempio con dati neonati (richiede file neonati.csv nella directory di lavoro)
neo <- read.csv("neonati.csv", sep = ";", header = TRUE)
head(neo)
#>   Peso settimane  fuma
#> 1 2940        38     S
#> 2 2420        36     S
#> 3 2760        39     S
#> 4 2440        35     S
#> 5 3301        42     S
#> 6 2715        36     S
str(neo)
#> 'data.frame':    32 obs. of  3 variables:
#>  $ Peso     : int  2940 2420 2760 2440 3301 2715 3130 2928 3446 2957 ...
#>  $ settimane: int  38 36 39 35 42 36 39 39 42 39 ...
#>  $ fuma     : chr  "    S" "    S" "    S" "    S" ...

Un data frame può contenere colonne di tipo diverso (numerico, carattere, fattore), a differenza di una matrice che è omogenea.


4 Trasformare variabili in fattori e ricodificare

4.1 Da numerico a fattore

In AutoBi alcune variabili sono codificate come numeri interi pur essendo qualitative. Occorre trasformarle esplicitamente in fattori.

# Trasformiamo MARITAL in fattore e assegnamo le etichette
AutoBi$MARITAL <- factor(AutoBi$MARITAL)
levels(AutoBi$MARITAL) <- c("married", "single", "widowed", "divorced")
str(AutoBi$MARITAL)
#>  Factor w/ 4 levels "married","single",..: NA 2 2 1 4 1 2 2 2 2 ...
summary(AutoBi$MARITAL)
#>  married   single  widowed divorced     NA's 
#>      624      650       15       35       16

4.2 Unire categorie (ricodifica)

Possiamo ridurre il numero di livelli unendo alcune categorie:

# Unire "widowed" e "divorced" in "previouslymarried"
levels(AutoBi$MARITAL) <- c("married", "single", "previouslymarried", "previouslymarried")
levels(AutoBi$MARITAL)
#> [1] "married"           "single"            "previouslymarried"
table(AutoBi$MARITAL)
#> 
#>           married            single previouslymarried 
#>               624               650                50

4.3 Trasformare variabili quantitative in classi: cut()

La funzione cut() converte una variabile numerica continua in un fattore ordinato con classi di valori.

range(AutoBi$CLMAGE, na.rm = TRUE)
#> [1]  0 95
# 6 classi di uguale ampiezza
CLMAGEclass_eq <- cut(AutoBi$CLMAGE, breaks = 6)
levels(CLMAGEclass_eq)
#> [1] "(-0.095,15.8]" "(15.8,31.7]"   "(31.7,47.5]"   "(47.5,63.3]"  
#> [5] "(63.3,79.2]"   "(79.2,95.1]"
# Classi di ampiezza diversa (definite manualmente)
CLMAGEclass <- cut(AutoBi$CLMAGE, breaks = c(-1, 15, 24, 36, 50, 95))
levels(CLMAGEclass)
#> [1] "(-1,15]" "(15,24]" "(24,36]" "(36,50]" "(50,95]"
table(CLMAGEclass)
#> CLMAGEclass
#> (-1,15] (15,24] (24,36] (36,50] (50,95] 
#>     144     280     269     299     159

Nota sulla notazione: (a, b] significa che la classe include b ma non a. I valori fuori dall’intervallo specificato diventano NA.

# Aggiungere la nuova variabile al data frame
AutoBi <- cbind(AutoBi, CLMAGEclass)
str(AutoBi[, c("CLMAGE", "CLMAGEclass")])
#> 'data.frame':    1340 obs. of  2 variables:
#>  $ CLMAGE     : int  50 28 5 32 30 35 19 34 61 NA ...
#>  $ CLMAGEclass: Factor w/ 5 levels "(-1,15]","(15,24]",..: 4 3 1 3 3 3 2 3 5 NA ...

5 Esercizi

5.1 Esercizio 1 – Classificazione delle variabili

Carica il dataset Cars93 dal package MASS e classifica almeno 6 variabili secondo lo schema qualitativa/quantitativa e, dove applicabile, sconnessa/ordinale o discreta/continua.

library(MASS)
data("Cars93")
str(Cars93)
# Scrivi qui la tua classificazione come commenti:
# es. Type: qualitativa ordinale (Small < Compact < Midsize < Large < Van)

Suggerimento: usa ?Cars93 per leggere la descrizione delle variabili.


5.2 Esercizio 2 – Fattori e ricodifica

Utilizziamo il dataset AutoBi. Esegui le seguenti operazioni:

  1. Trasforma ATTORNEY in un fattore con etichette "yes" e "no".
  2. Trasforma CLMSEX in un fattore con etichette "M" e "F".
  3. Verifica con str() che le trasformazioni siano avvenute correttamente.

Soluzione:

AutoBi$ATTORNEY <- factor(AutoBi$ATTORNEY)
levels(AutoBi$ATTORNEY) <- c("yes", "no")

AutoBi$CLMSEX <- factor(AutoBi$CLMSEX)
levels(AutoBi$CLMSEX) <- c("M", "F")

str(AutoBi[, c("ATTORNEY", "CLMSEX")])
#> 'data.frame':    1340 obs. of  2 variables:
#>  $ ATTORNEY: Factor w/ 2 levels "yes","no": 1 2 2 1 2 1 1 1 2 2 ...
#>  $ CLMSEX  : Factor w/ 2 levels "M","F": 1 2 1 1 1 2 1 2 2 1 ...

5.3 Esercizio 3 – Classi di valori

Usando la variabile LOSS di AutoBi:

  1. Trova il range della variabile (range()).
  2. Crea una variabile in classi usando i quartili come punti di separazione (quantile()).
  3. Aggiungi la nuova variabile al data frame con il nome LOSSclass.
  4. Conta quante osservazioni ci sono in ogni classe.

Soluzione:

range(AutoBi$LOSS, na.rm = TRUE)
#> [1]    0.005 1067.697
q <- quantile(AutoBi$LOSS)
AutoBi$LOSSclass <- cut(AutoBi$LOSS, breaks = q, include.lowest = TRUE)
levels(AutoBi$LOSSclass)
#> [1] "[0.005,0.64]"    "(0.64,2.33]"     "(2.33,3.99]"     "(3.99,1.07e+03]"
table(AutoBi$LOSSclass)
#> 
#>    [0.005,0.64]     (0.64,2.33]     (2.33,3.99] (3.99,1.07e+03] 
#>             336             334             335             335

5.4 Esercizio 4

Rispondi brevemente alle seguenti domande (puoi scrivere le risposte come commenti nel codice):

  1. Perché è importante distinguere tra variabili qualitative e quantitative prima di iniziare l’analisi?
  2. Un codice postale (es. 34121) è una variabile quantitativa o qualitativa? Motiva la risposta.
  3. Cosa succede se applichi cut() e alcuni valori del vettore numerico cadono fuori dagli estremi dei breaks specificati?
# Scrivi le tue risposte qui come commenti:
# 1. 
# 2. 
# 3. 
# Puoi verificare sperimentalmente il punto 3:
x <- c(1, 5, 10, 15, 100)
cut(x, breaks = c(0, 5, 10, 20))  # cosa succede al valore 100?
#> [1] (0,5]   (0,5]   (5,10]  (10,20] <NA>   
#> Levels: (0,5] (5,10] (10,20]

5.5 Cheatsheet

# ESPLORARE UN DATA FRAME
str(df)           # struttura e tipi
head(df)          # prime 6 righe
summary(df)       # riassunto per colonna

# TRASFORMARE IN FATTORE
x <- factor(x)
levels(x) <- c("etichetta1", "etichetta2")

# UNIRE CATEGORIE
levels(x) <- c("A", "A", "B")   # unisce i primi due livelli in "A"

# Quantili 
quantile(x) # min, primo/secondo/terzo quartile, max

# CLASSI DI VALORI
cut(x, breaks = n)                          # n classi di uguale ampiezza
cut(x, breaks = c(a, b, c))                 # classi di ampiezza diversa
cut(x, breaks = quantile(x),
    include.lowest = TRUE)                  # classi ai quartili

# VALORI MANCANTI
sum(is.na(x))           # numero di NA
x[!is.na(x)]            # rimuovere NA