Gestione avanzata dei fattori

Nell’ultimo post abbiamo parlato delle variabili di tipo fattore, per cercare di capire in cosa queste si differenzino dalle più semplici variabili di tipo carattere o numerico. Ora vedremo qualche funzione per manipolare i fattori, per ricodificarli e adattarli alle nostre esigenze.

Procuriamoci subito dei dati su cui lavorare. Sul portale open data del Comune di Cagliari è disponibile un dataset che contiene tutti gli incidenti stradali del 2014 avvenuti nel territorio comunale in cui sia intervenuta una pattuglia del corpo di Polizia Locale. Qui c’è la pagina di descrizione del dataset, mentre questo è il link diretto al file csv.

incidenti <- read.csv2("http://www.comune.cagliari.it/resources/cms/documents/Cagliari_PoliziaLocale_SinistriStradali_2014.csv")
&#91;/code&#93;

Il dataset contiene un bel po' di variabili (descritte sommariamente <a href="http://www.comune.cagliari.it/portale/it/opendata_visualizza_contenuto.page?modelId=45&contentId=SCH80418" target="_blank">qui</a>); noi ci concentreremo sul fattore <b>tipologia</b>, che classifica gli incidenti per tipo. Nel seguito di questo post eseguiremo una serie di operazioni su questo fattore; per evitare di alterare la variabile originale, salviamo la colonna &ldquo;tipologia&rdquo; del dataset &ldquo;incidenti&rdquo; in un nuovo oggetto, esterno al data frame:

[code language="R"]
tipoIncidenti <- incidenti$tipologia
&#91;/code&#93;

<h3 style="margin-top: 1.5em; margin-bottom: 0em;">I livelli del fattore</h3>
<hr style="margin-top: 0.4em; margin-bottom: 1.5em; width: 80%; background-color: black; height: 2px;">

<b>Prima domanda:</b> quanti livelli presenta il fattore tipologia? La risposta ce la fornisce il comando <b>nlevels</b>:

[code language="R"]
> nlevels(tipoIncidenti)
[1] 5

Seconda domanda: quali sono i livelli del fattore tipologia? La risposta ce la fornisce il comando levels, che estrae il vettore di etichette:

> levels(tipoIncidenti)
[1] "Danneggiamento"                         
[2] "Incidente stradale con feriti"          
[3] "Incidente stradale mortale"             
[4] "Incidente stradale per caduta di pedone"
[5] "Incidente stradale senza feriti"

Possiamo anche estrarre ogni singolo livello utilizzando le parentesi quadre. Per esempio, per estrarre il quarto livello:

> levels(tipoIncidenti)[4]
[1] "Incidente stradale per caduta di pedone"

Il fattore raggruppa gli incidenti sulla base di cinque categorie: la prima comprende generici danneggiamenti derivanti da buche sul manto stradale, caduta di rami dagli alberi, urto contro cassonetti, ecc., mentre le altre categorie comprendono incidenti stradali veri e propri.

Terza domanda: quante osservazioni sono presenti per ogni livello del fattore? La risposta ce la fornisce il comando table:

> table(tipoIncidenti)
tipoIncidenti
                         Danneggiamento           Incidente stradale con feriti 
                                    170                                     571 
             Incidente stradale mortale Incidente stradale per caduta di pedone 
                                      5                                      66 
        Incidente stradale senza feriti 
                                    634

Nel caso in cui le etichette che descrivono i nomi dei fattori siano lunghe (come in questo caso), possiamo associare il comando cbind al comando table, in modo da avere un output più ordinato:

> cbind(table(tipoIncidenti))
                                        [,1]
Danneggiamento                           170
Incidente stradale con feriti            571
Incidente stradale mortale                 5
Incidente stradale per caduta di pedone   66
Incidente stradale senza feriti          634

Ricodificare i livelli


Le etichette che costituiscono i nomi dei livelli sono piuttosto lunghe. Soprattutto quando si vogliono visualizzare i dati in un grafico, è bene che le etichette siano quanto più concise possibile. Possiamo rinominare i livelli sfruttando sempre il comando levels, utilizzandolo per attribuire al fattore un nuovo vettore di nomi:

newlev <- <- c("Danni", "con feriti", "con morti", "caduta pedone", "senza feriti")
levels(tipoIncidenti) <- newlev
&#91;/code&#93;

Attenzione: all'interno del vettore <i>newlev</i>, i nomi devono essere disposti nello stesso ordine in cui sono disposti i livelli nel fattore, pena l'attribuire ai livelli le etichette sbagliate.

Verifichiamo il risultato:

[code language="R"]
> levels(tipoIncidenti)
[1] "Danni"         "con feriti"    "con morti"     "caduta pedone"
[5] "senza feriti"

> table(tipoIncidenti)
tipoIncidenti
        Danni    con feriti     con morti caduta pedone  senza feriti 
          170           571             5            66           634

Possiamo ricodificare i livelli anche singolarmente. Per esempio, per trasformare l'etichetta “Danni” in “danni”:

> levels(tipoIncidenti)[1] <- "danni"
> levels(tipoIncidenti)
[1] "danni"         "con feriti"    "con morti"     "caduta pedone"
[5] "senza feriti"

Accorpare i livelli


Immaginiamo di voler raggruppare i sinistri in due categorie: quelli con feriti o morti (“tipo 1”) e quelli senza alcuna conseguenza fisica per le persone coinvolte (“tipo 2”). Per eseguire questa operazione possiamo sfruttare ancora una volta la funzione levels, attribuendo la medesima etichetta ai livelli che vogliamo accorpare:

levels(tipoIncidenti) <- c("tipo 2", "tipo 1", "tipo 1", "tipo 2", "tipo 2")
&#91;/code&#93;

Verifichiamo il risultato:

&#91;code language="R"&#93;
> levels(tipoIncidenti)
[1] "tipo 2" "tipo 1"

> table(tipoIncidenti)
tipoIncidenti
tipo 2 tipo 1 
   870    576

Come si vede, ci sono 576 incidenti di tipo 1 (somma di “con feriti” e “con morti”) e 870 incidenti di tipo 2 (somma di “danni”, “caduta pedone” e “senza feriti”).

Riordinare i livelli


La precedente aggregazione dei livelli ha prodotto un risultato per alcuni versi sconveniente: l'etichetta “tipo 2” costituisce il primo livello, mentre l'etichetta “tipo 1” il secondo livello. Ecco cosa succede se proviamo a visualizzare in un grafico a barre il numero di incidenti per ogni tipologia:

> barplot(table(tipoIncidenti))

barplot incidenti

I livelli vengono visualizzati nell'ordine con cui sono stati codificati, per cui il tipo 2 compare prima del tipo 1. Per ovviare a questo problema possiamo usare la funzione factor, che consente di rifattorizzare una variabile:

> tipoIncidenti <- factor(tipoIncidenti, levels=c("tipo 1","tipo 2"))
&#91;/code&#93;

Adesso i livelli sono stati riordinati, per cui sarà &ldquo;tipo 1&rdquo; a comparire per primo:

&#91;code language="R"&#93;
> table(tipoIncidenti)
tipoIncidenti
tipo 1 tipo 2 
   576    870
> barplot(table(tipoIncidenti))

barplot incidenti

Si noti che la stessa funzione factor, al pari della funzione levels, può essere usata per modificare i nomi dei livelli:

> tipoIncidenti <- factor(tipoIncidenti, labels=c("Tipo 1","Tipo 2"))
&#91;/code&#93;

<h3 style="margin-top: 1.5em; margin-bottom: 0em;">Fattori con livelli ordinati</h3>
<hr style="margin-top: 0.4em; margin-bottom: 1.5em; width: 80%; background-color: black; height: 2px;">

Per come l'abbiamo concepito fino a questo momento, un fattore non è altro che una variabile qualitativa su <b>scala nominale</b>. In realtà, il tipo fattore è pensato anche per registrare dati misurati su <b>scala ordinale</b>. Ripartiamo dall'inizio e riprendiamo l'originale vettore &ldquo;tipologia&rdquo; del dataset &ldquo;incidenti&rdquo;, salviamolo nell'oggetto tipoIncidenti abbreviando i nomi dei livelli:

[code language="R"]
tipoIncidenti <- factor(incidenti$tipologia, labels=c("danni", "con feriti", "con morti", "caduta pedone", "senza feriti"))
&#91;/code&#93;

Ammettiamo che sia possibile dare un ordinamento alle categorie del fattore sulla base della gravità: al livello più basso ci sarà la categoria "Danneggiamento", poi "Incidente stradale per caduta di pedone", poi "Incidente stradale senza feriti", quindi "Incidente stradale con feriti" e infine "Incidente stradale mortale".

Per prima cosa, creiamo un vettore che contiene i nomi dei livelli disposti nell'ordine desiderato:
&#91;code language="R"&#93;
lev <- c("danni", "caduta pedone", "senza feriti", "con feriti", "con morti")
&#91;/code&#93;

Si noti che avremmo potuto ottenere lo stesso risultato anche utilizzando il comando levels:

&#91;code language="R"&#93;
> lev <- levels(tipoIncidenti)&#91;c(1,4,5,2,3)&#93;
> lev
[1] "danni"         "caduta pedone" "senza feriti"  "con feriti"   
[5] "con morti"

A questo punto, rifattorizziamo il vettore utilizzando il comando factor, impostando a TRUE l'argomento ordered:


tipoIncidenti <- factor(tipoIncidenti, levels=lev, ordered=TRUE) [/code] Il comando str, adesso, indicherà che tipoIncidenti è una variabile di tipo fattore, ma i cui livelli sono ordinati, dove danni < caduta pedone < senza feriti < con feriti < con morti. [code language="R"] > str(tipoIncidenti)
Ord.factor w/ 5 levels "danni"<"caduta pedone"<..: 3 3 3 3 3 1 2 4 3 4 .. [/code] Si noti che lo stesso risultato avremmo potuto ottenerlo con la funzione ordered:


> tipoIncidenti <- ordered(tipoIncidenti, levels=lev) [/code] L'ordinamento dei livelli di un fattore è una sottigliezza che assume una sua utilità esclusivamente nell'adattamento di un modello statistico. È comunque importante che una variabile misurata su scala ordinale sia codificata nel modo corretto, soprattutto quando ci si passa i dati tra colleghi e certi dettagli rischiano di essere omessi e talvolta male interpretati.

Print Friendly

Lascia un Commento