26 ottobre 2009

Vectorizing computing in R

Un forte limite nell'utilizzo di R (in particolare per chi è già abituato a sviluppare in altri linguaggi di programmazione) è la lentezza dell'esecuzione di algoritmi basati sui classici "cicli di for". Eseguire un blocco di codice ripetutamente, infatti, è un'operazione concettualmente semplice che, quindi, ci permette di gestire facilmente la ripetizione di un insieme di "operazioni" (eventualmente effettuando il controllo di alcune condizioni con dei sempici "if"). Putroppo in R è fortemente sconsigliato questo approccio e per questo motivo si parla di vectorizing computing: trasformare il ciclo di for in operazioni tra vettori o matrici. Quindi la ripetizione di un blocco di codice controllato da un contatore deve essere trasformato, ad esempio, in un prodotto di matrici. Questo metodo di sviluppo ha come fine quello di sfruttare al meglio il motore di calcolo di R, che è appunto ottimizzato per il calcolo matriciale. Ovviamente questo approccio può portare ad altro tipo di problemi, ossia alla gestione dei dati mediante matrici "troppo grandi" e difficilmente gestibili. L'esperienza comunque permette di arrivare alla soluzione megliore, e non credo si possa stilare un elenco di situazioni in cui preferire un approccio ad un altro: ogni soluzione va valutata singolarmente "sul campo" (...bella novità...).
Riporto di seguito alcuni esempi di for in R con le relative "vettorizzazioni".

Creo un vettore p composto da 500.000 valori estratti da una normale standardizzata e, da questo, ne derivo il vettore formato dagli stessi 500.000 valori rapportati alla loro somma. Forse la vettorizzazione di questo esempio è veramente banale, ma serve a rendersi conto dei tempi di esecuzione.
Il relativo ciclo di for è semplicissimo:


p<-rnorm(500000)
s<-sum(p)
for (i in 1:500000) p[i]<-p[i]/s


Per la valutazione dei tempi di esecuzione basta osservare il risultato di system.time(),che esegue il codice in parentesi e riporta il tempo in secondi. Nel nostro caso ci limitiamo ad osservare il tempo elapsed (in blu è roportato l'output di R):


system.time(for (i in 1:500000) p[i]<-p[i]/s)
user system elapsed
3.2 0.0 3.2


La cosiddetta vettorizzazione è in tal caso banale (p/s), ma il risultato è notevole:


system.time(p<-p/s)
user system elapsed
0.0 0.02 0.02



In termini assoulti, un risparmio di 3.18 secondi può sembrare inutile, ma se si ragiona in termini relativi si osserva un risparmio del 99% del tempo di esecuzione, quindi molto importante per calcoli più complessi!

Prendiamo in esame un esempio in cui la vettorizzazione è meno immediata.
Consideriamo un insieme di 1.000.000 di dati estratti da una normale standardizzata. Pensate ad esempio ad un tipica applicazione in ambito industriale, in cui si controlla che il prodotto rispetti determinate caratteristiche (peso, dimensioni, ecc. ...) e in cui ci si aspetti che gli "errori" nella produzione siano distribuiti normalmente. In elaborazioni effettuate in tale ambito, quindi, si dispone di un vettore di questo tipo. I calcoli che svolgo di seguito, comunque, sono solo a titolo di esempio e non rappresentano alcun indicatore o controllo tipico della statistica industriale.
Immaginiamo di avere i dati in forma matriciale: 1000 casi controllati (in riga) per 1000 caratteristiche (in colonna). Da questo dataset vogliamo ricavare una matrice di valori dicotomici, con 1 o 0 a seconda che il valore sia maggiore o uguale a zero (1), oppure negativo (0), rispettivamente.
Anche in questo caso il codice da usare per un ciclo di for è immediato:


N<-1000
mtx<-matrix(rnorm(N*N),N,N)
mtx2<-matrix(0,N,N)

system.time(for (i in 1:N) for (j in 1:N) if(mtx[i,j]>=0) mtx2[i,j]<-1)
user system elapsed
6.20 0.00 6.52


La vettorizzazione si può effettuare mediante il comando ifelse(), che analizza ogni singolo elemento della matrice e esegue un'operazione a seconda che il test sia positivo o negativo (da notare che è differente da if() else):


system.time(mtx2<-ifelse(mtx>=0,1,0))
user system elapsed
0.90 0.05 0.98



Anche qui la riduzione del tempo di elaborazione è molto significativa: 85%.

Riporto infine un esempio di vectorizing computing in cui si fa uso di matrici triangolari, molto utili in questo tipo di programmazione in R.
Consideriamo sempre la matrice mtx di 1000 casi per 1000 caratteristiche. Per ogni singolo caso (vettore riga) vogliamo calcolare il rapporto tra l'(i)-esimo elemento e la somma dei successivi 1000-i elementi (quindi la somma dei casi da (i+1) a 1000). La soluzione con un for necessita lo scorrimento dell'intera matrice in questo semplice modo:


N<-1000
mtx<-matrix(rnorm(N*N),N,N)
mtx2<-matrix(0,N,N) system.time(for (i in 1:N) for (j in 1:(N-1)) mtx2[i,j]<-mtx[i,j]/sum(mtx[i,(j+1):N]))
user system elapsed
37.99 0.17 39.93

Per la trasformazione in codice vettorizzato faccio uso del comando lower.tri(), che crea una matrice triangolare inferiore con valori TRUE e FALSE. Dal relativo help di R: "Returns a matrix of logicals the same size of a given matrix with entries TRUE in the lower or upper triangle".

Questo il codice:



N<-1000
mtx<-matrix(rnorm(N*N),N,N)
mtx2<-matrix(0,N,N)
system.time(mtx2<-mtx/(mtx%*%(1*lower.tri(matrix(0,N,N)))))
user system elapsed
2.55 0.00 2.67


Ho praticamente sostituito lo scorrimento dei dati mediante for, con un prodotto matriciale in cui vi è un'opportuna matrice triangolare inferiore. La riduzione del tempo di elaborazione è del 93%.

16 ottobre 2009

The Elements of Statistical Learning : download del libro !

Ho scoperto (solo ora) che è possibile scaricare il libro in oggetto!!!! Sicuramente da non perdere!!!
Downoald qui.

25 agosto 2009

R in Word: SWord

Un rientro dalle ferie con una bella novità: SWord per implementare soluzioni analitiche direttamente in Word, utilizzando R come motore di analisi dati. Il sito ufficiale è sempre quello di Statconn. Analogamente a quanto avviene in RExcel (come già trattato in miei altri post) è possibile direttamente in Word lavorare con R in modalità background o foreground. L'uso di tale package permette quindi di sviluppare un sistema di "reporting" mediante questo diffusissimo software di creazione di documenti. Si potrebbe pensare a "modelli" di documenti Word in cui riportare i risultati delle nostre analisi statistiche "al volo": l'utente apre il file .doc, clicca un tasto e visualizza i risultati delle eleborazioni in formato "testuale". Ovviamente, dietro le quinte ci sarà l'importazione di un dataset in R (ad esempio da un database esterno), l'elaborazione di un modello statistico e la visalizzazione dei risultati nel testo! Un'altra possibilità potrebbe essere l'utilizzo di SWord per creare dei documenti "interattivi" per illustrare il funzionamento di R. L'utente legge delle istruzioni e clicca un bottone per visulizzare ciò che avviene in R. Riporto un esempio semplicissimo, rimandando al sito ufficiale per gli approfondimenti. Come prima cosa, l'installazione: un semplice click sul file .exe che trovate qui. Sottolineo che l'uso in word di tale package si basa sui "Codici di campo", ossia dei "tag" molto utili per i quali si rimanda alla documentazione ufficiale. Per tale motivo è importante accertarsi che sia impostata la visualizzazione di essi. In Word 2003 si possono seguire le seguenti istruzioni: Strumenti > Opzioni > Visualizza > segno di spunta in corrispondenza di "Codici di campo". Consiglio anche di impostare "Ombreggiatura campo" a "Sempre".

23 giugno 2009

Prevedere il "brain drain" mediante un algoritmo

Uso intensivo dei dati come guida alle decisioni umane, una filosofia comune ormai a molte realtà aziendali.
Ovviamente google è un esempio vincente di uso di dati, e lo sviluppo di un modello per prevedere gli individui "più probabili" all'abbandono dell'azienda è un bel tentativo di previsione del comportamento umano!
Non ho trovato comunicazioni ufficiali della Google Inc. in cui vengono spiegati i dettagli dell'algoritmo (... chissà se c'è di mezzo l'uso di R ...), ma qui trovate maggiori informazioni.

22 maggio 2009

Alberi di Classificazione in Excel

Il titolo del post è veramente "forte", nel senso che sto dicendo che in Excel è possibile ricorrere ai famosi Alberi di Classificazione, più noti con il termine di CART: Classification and Regression Trees. In realtà c'è il solito trucchetto: il dataset è in Excel, ma le elaborazioni le fa R. La comunicazione tra i due strumenti, come ampiamente ripetuto in questo blog, avviene mediante statconnDCOM.
Prima di tutto, quindi, è necessario avere sulla propria macchina i giusti tools, come già descritto in questo mio precedente post. In realtà alla data in cui scrivo è disponbile RAndFriends, che fino a poco tempo fa era disponibile solo in versione "light". Io direi quindi di installare tutto, evitando scelte personalizzate delle componenti . In genere, comunque, nelle applicazioni eseguite in XP non ho mai riscontrato problemi di installazione (come ad esempio installare solo statconnDCOM).

Per quanto riguarda gli Alberi di Classificazione si fa riferimento a questa monografia, il cui progetto è coperto da copyright ed il cui software originale è distribuito dalla Salford System. In R è disponibile la libreria rpart, il cui maintainer è Brian Ripley (che a sua volta ha "portato" in R il codice disponibile in SPLUS, vedi qui per maggiori info). In R quindi si parla di Recursive partitioning and regression trees, e considerando l'autore dovremmo poter avere una certa fiducia per quanto riguarda l'affidabilità del codice!
La teoria che è alla base è abbastanza semplice da un punto di vista matematico, io infatti ho ritenuto molto scorrevole da lettura del libro di Friedman.

Per quanto riguarda lo sviluppo in Excel, direi che è praticamente semplicissimo, non dovendo fare altro che riportare in VBA il codice che si è testato direttamente in R. Nell'esempio seguente ho lavorato in modalità "Macro programming", ossia ricorrendo a RExcel.xla. Nell'esercizio riportato in Access, invece, si è sviluppato in modalità "RDCOM Server". La prima, infatti, è possibile solo in Excel. Nessuno comunque ci vietava di fare ricorso anche qui in Excel all'oggetto StatConnector. Su questa differenza, comunque, scriverò presto un post (nel frattempo, quello che c'è da sapere è sempre qui!!!!!).

Passiamo ora alla descrizione del dataset utilizzato per l'esempio.
Ho pensato di toccare un argomento molto attuale, ossia la previsione dello spam. Trattasi di un tipico esempio di classificazione di una variabile dicotomica sulla base di informazioni relative al testo dell'email. Quindi la variabile risposta assumerà valori 0 (non spam) o 1 (spam).
Nel nostro dataset di esempio le variabile predittive sono semplicemente variabili di conteggio relative all presenza (in %) di alcune parole. Potete scaricare i dati e tutte le informazioni direttamente qui.
Riporto di seguito il codice associato ad un pulsante di comando. Al suo click ai avvia R in back-end e si caricano in R i dati disponibili in Excel (in un foglio nominato "dbxls"). Successivamente avviene la stima del modello e la visualizzazione dell'albero di classificazione finale. Ovviamente quando si chiude il server (Call Rinterface.StopRServer) si chiuderà anche la visualizzazione del grafico. Per evitare questo ho semplicemente messo un MsgBox che permette la visualizzazione dell'immagine fino al click su OK. Se volete riprovare ad eseguire il tutto dovete cambiare i nomi delle variabili predittive in v1, v2, ... , v57, mentre l'ultima sarà nominata "spam" (appunto la variabile dipendente).
Trattandosi di un esempio, non mi sono soffermato su vari aspetti della costruzione dell'Albero (quali previsione e pruning), ma la loro implementazione è semplice una volta capito il meccanismo.
Riporto il codice VBA:

'*************************************
Private Sub cmd_Click()
On Error GoTo errore
Dim rng As Range
Set rng = Worksheets("dbxls").Range("A1:BF4602")
Call Rinterface.StartRServer
Call Rinterface.RRun("library(rpart)")

Call Rinterface.PutDataFrame("db", rng)
Call Rinterface.RRun _
("db<-cbind(db[,1:57],spam=as.factor(db[,58]))") Call Rinterface.RRun("fit<-rpart(spam~.-spam, data=db)") Call Rinterface.RRun("plot(fit)") Call Rinterface.RRun("text(fit)")

MsgBox _
"Cliccando ok procedi con la chiusura di RServer"
Call Rinterface.StopRServer


Exit Sub
errore:
Call Rinterface.StopRServer

End Sub
'*************************************

La bellezza di tale metodo sta prima di tutto nell'immediatezza del grafico. Come potete vedere, facendo "cadere" un dato attraverso l'albero si arriva immediatamente alla soluzione:
  1. v53 è minore di 0.05? Sì, allora vai a destra dell'albero.
  2. v25 è >= 0.4? Sì, allora vai a destra dell'albero.
  3. spam=1
quindi la previsione più probabile è che l'email in questione sia spam! Una piccola curiosità: in tali dati la variabile più significativa (quella che determina lo split più discriminante) è la v53, ossia la presenza in percentuale del carattere dollaro: "$". Se tale percentuale supera il 5.5% si passa ad analizzare la v25, ossia la presenza della parola "hp". Se quest'ultima è a sua volta presente con una percentuale maggiore o uguale al 40% allora l'email è considerata spam. Sicuramente più interessante (in quanto meno scontata) è l'analisi dell'albero a sinistra del primo split:
  1. v53: percentage of character "$"
  2. v25: percentage of word "hp"
  3. v7: percentage of word "remove"
  4. v52: percentage of character "!"
  5. v57: sum of length of uninterrupted sequences of capital letters
  6. v16: percentage of word "free".
Infine una piccola considerazione.
La "facilità" di cui parlo sempre per l'uso di R ed Excel (o Access) è sempre legata ad una certa padronanza di R e di VBA, ovviamente! Nello stesso tempo è necessaria una certa conoscenza teorica del metodo che si andrà ad utilizzare. Inoltre l'uso contemporaneo di Excel/Access ed R è da me pensato per un'implementazione (facile) di modelli statistici di analisi e previsione da parte di uno statistico che lavora per utente finale "non esperto" (e che quindi vuole una soluzione finale del tipo "click and go" :-) .

28 aprile 2009

OLAP e Statistical Databases: similarità nella terminologia

Veramente interessante questo articolo di Arie Shoshani sulle similarità (e differenze) esistenti tra le terminologie tipiche della Statistica, da un lato, e del Data Mining , dall'altro (...quest'ultimo inteso in senso molto generale...). Anche se di una decina di anni fa, l'articolo è sicuramente attuale per chi lavora in ambito "analitico". Chi infatti ha una formazione "statistica" e si trova a lavorare con i database, rifletterà sicuramente sulle analogie esistenti tra i termini normalmente utilizzati nei testi di Statistica e quelli molto utilizzati dai produttori di software per il Data Mining e la Business Intelligence. L'esempio più evidente è l'analogia tra multidimensional space e data cube. Direi che di grande significatività è la tabella dell'articolo sulle corrispondenze tra le due differenti terminologie:





02 aprile 2009

Le novità di R(D)COM: statconnDCOM

Da un po' aspettavo questo aggiornamento e devo dire che le cose sono cambiate abbastanza! Non solo è cambiato il sito, ma anche le modalità di installazione, configurazione e download. Diventa anche più evidente la relazione tra il progetto rcom e la statconn di Thomas Baier ed Erich Neuwirth (e quindi i relativi corsi di formazione).
La novità più evidente è la possibilità di scaricare RAndFriendsLight, ossia un pacchetto che contemporaneamente installa e configura tutto il necessario:
R 2.8.1
rscproxy 1.0-12
rcom 2.xx
RExcel 3.0-11 .
Credo comunque che la situazione più frequente sia quella in cui lo sviluppatore disponga già di R sulla propria macchina. In tale caso (considerando che è obbligatoria una versione >= 2.7.2) sarà necessario optare per le altre modalità indicate nell'area downolad.
La procedura di configurazione, comunque, è chiaramente descritta qui.
Ovviamente con questa nuova struttura del progetto si sottolinea (giustamente!!!) che la redistribuzione del prodotto in altre soluzioni necessità di una licenza commerciale...

24 marzo 2009

I package "orfani" di R

Mi son sempre chiesto quale fosse la procedura adottata dal team di R nel caso in cui il maintainer di una libreria si rendesse irreperibile o non fosse più disposto al relativo "sviluppo". Ovviamente la risposta è sul sito del CRAN: semplicemente il pacchetto continuerà ad essere disponibile fin quando passerà il test <<R CMD check>>. Ora che scrivo ve ne sono 57 di librerie orphaned, quindi effettivamente si corre un rischio (...a mio parere minimo...) di ritrovarsi senza il pacchetto sul quale si era investito tempo e denaro...

27 febbraio 2009

Numeri pseudo-casuali e software statistici

La generazione di numeri pseudo-casuali è un argomento di fondamentale importanza per le applicazioni in statistica. La "bontà" dell'algoritmo utilizzato in un software è quindi decisivo per la validità delle simulazioni eseguite mediante esso. In questo breve post intendo soffermermi sugli algoritmi impementati in R, SAS ed SPSS.
L'argomento è stato trattato ampiamente dagli studiosi e continua ad attirare l'attenzione di statistici ed informatici (...ammesso che in tale ambito sia possibile fare questa distinzione tra le due discipline...), ed ovviamente gli sviluppatori dei software sopra citati non possono che seguire gli sviluppi della scienza.
I numeri peseudo-casuali sono chiamati in tale modo appunto perché sono "deterministici" ma "sembrano" casuali. Sono generati da un algoritmo implementato in un calcolatore (quindi deterministisco) ma soddisfano una serie di proprietà che li fanno "sembrare" casuali per gli scopi prefissati, quindi per la simulazione di un qualche fenomeno. L'algoritmo più famoso è il Generatore Lineare Congruente (Linear Congruential Generators) riassunto dalla seguente funzione di trasferimento:
f(x) = (ax + c) mod m .
mod è la funzione che fornisce il resto della divisione intera, ossia:
x mod y = y ( x/ y - [x/y] )
dove [h] è la parte intera inferiore di h. Quindi ad esempio 11 mod 3 = 3 * (11/3 - [11/3]) = 3*(3.6667 - 3) = 2.
Qundi si fissano a, c ed m, si parte da un valore inziale X_0 e si ottiene X_1 = f(X_0) . A questo punto si genererà il numero pseudo-casuale (in [0, 1[ ) mediante una funzione output (la più semplice è X_j /m). La funzione di trasferimento più semplice e più conosciuta è invece quella di Park-Miller, in cui si impone semplicemente c=0.
Per una trattazione teorica molto chiara ed esaustiva si legga qui.
La tipologia di algoritmo appena citato è stato nel tempo criticato e praticamente sostituito dal generatore di Mersenne-Twister (M-T).
Ovviamente, poiché R è sempre "avanti" :-) , quest'ultimo è l'algoritmo di default già da tempo, mentre gli altri software sono stati aggiornati da un po'.
In SAS infatti, fino alla versione 9.0, l'unico algoritmo disponibile era il Generatore Lineare Congruente nella versione di Park-Miller con i seguenti parametri:
c=0
a=397204094
m=2^31-1 .
Solo dalla 9.1 è finalmente disponibile anche la funzione RAND che appunto si basa sull'algoritmo di M-T!!!! (chi vuole approfondire può leggere qui).
Mi dilungo sul SAS perché trovo molto macchinoso il procedimento di gestione delle sequenze dei numeri casuali. Utilizzando la funzione RANUNI(seed) in un datastep, cambiare il seed (ossia il valore di x_0 nel generatore) non avrà influenza sulla sequenza di numeri casuali poiché l'estrazione avverrà sempre dallo stesso stream (ossia flusso, ma in inglese fa più figo :-) ). Per avere un controllo della sequenza sarà necessario ricorrere a CALL RUNUNI(seed) dove il seed deve essere una variabile e non una costante.
Si provi ad eseguire il seguente codice per capire la distinzione:

data test;
do i=1 to 10;
x = RANUNI(1);
output;
end;

run;

data test_i;
do i=1 to 10;
x = RANUNI(i);
output;
end;
run;


data test_call;
do i=1 to 1;
call RANUNI(i,x); /*con ranuni(1,x) va in errore*/
output;
end;
run;


Per quanto riguarda infine l'SPSS, si faccia riferimento al menu " Trasforma / Generatori numeri casuali " per scoprire il tipo impostato. Consiglio ovviamente di utilizzare il generatore di Mersenne-Twister con inizializzazione casuale (ossia derivata dall'orologio di sistema). Più semplice forse farlo direttamente aprendo un file di sintassi .sps e settando mediante codice:
SET RNG=MT MTINDEX=RANDOM.

30 gennaio 2009

Licenze commerciali di R che spuntano come funghi...

Mentre un enorme gruppo di sviluppatori, più o meno volontari, garantisce lo sviluppo del software statistico più aggiornato del mondo, c'è chi pensa (giustamente) di fornire licenze commerciali di R che dovrebbero garantire un maggiore supporto ed una migliore funzionalità (altrimenti non resisterebbero molto sul mercato).
Queste sono quelle che conosco, ma solo di nome:
La mia paura è che gli sviluppatori di RDCOM seguano prima o poi una strada simile ... e diciamo pure che seguendo i relativi dibattiti nei newsgroup si comincia a respirare quest'aria...

07 gennaio 2009

Installazione di Latex in ambiente Windows

L'utilizzo di Latex per chi lavora in ambito statistico è sicuramente consigliato, soprattutto per evitare gli incovenienti dell'uso di Equation Editor in Word. La qualità "grafica" di un testo scritto in Latex è inoltre sorprendente, a patto di un piccolissimo sforzo iniziale per l'apprendimento. Ovviamente anche l'uso di Word a livello professionale (che non significa semplicemente cliccare su di un file .doc e poi scriverci sopra!) necessita di molta pratica e di approfondimenti. Quindi un po' di studio di Latex potrebbe davvero valerne la pena.
Come indicato nel titolo, faccio riferimento a Windows (così come in tutto il resto del blog). Le installazioni che ho eseguito fino ad ora sono avvenute tutte in XP, ma come sempre immagino che con pochi accorgimenti si possa facilmente generalizzare ad altre versioni.
Nell'illustrazione dei diversi step non mi soffermo sul significato delle diverse "componenti", un po' perché non ne ho le capacità e un po' perché esiste molto materiale in rete (il miglior punto di partenza e anche di arrivo è sicuramente il sito del GuIT).
Quindi di seguito riporto dei consigli veloci per l'installazione di tutto, mentre vi consiglio di leggere questo documento.
  1. installare MikTex
  2. installare TEXnicCenter
  3. installare GSView
  4. installare Ghostscript
Ora dovrebbe essere tutto pronto. Si riavvia il pc, si apre TEXnicCenter e partono alcuni messaggi che chiedono di indicare una directory. Trovate la risposta alle vostre domande in questo video:






28 novembre 2008

Nona Conferenza Nazionale di Statistica

Il prossimo 15 e 16 Dicembre si ripeterà a Roma l'appuntamento biennale della Conferenza Nazionale di Statistica. Io ci sono stato nel 2006 e credo ci andrò anche quest'anno. Consiglio la partecipazione a chiunque sia interessato a reperire informazioni sul mondo della Statistica Ufficiale italiana.
Questo il link di riferimento.

03 novembre 2008

Lezioni di Statistica su YouTube

In rete c'è veramente di tutto, perfino dei video-tutorials per R !
Ma quello che mi è piaciuto di più è il teorema di Bayes (in spagnolo) con tanto di sottofondo degli Enigma :-)

29 ottobre 2008

Odds Ratio in Statistica Medica e Sanitaria

Il concetto di Odds Ratio è ampiamente diffuso in Medicina, Epidemiologia, Statistica Medica, Statistica Sanitaria...e chi ne ha più ne metta! Normalmente ci si sforza di descrivere il concetto ad un pubblico di utenti "non esperti" cercando di rendere il più semplice possibile tale numero, che altro non è che un rapporto di rapporti :-) .
In base alle mie esperienze ho notato, invece, che molte volte è lo statistico stesso a perdere di vista il vero fine di tale indice, lasciandosi andare in riflessioni sugli aspetti "matematici" che poco interessano l'utente.
L'Odds Ratio si basa su di una tabella che è alla base di tutto, una tabella a doppia entrata relativa a due variabili dicotomiche: Fattore di Rischio ed Insorgenza Malattia.












Il fattore di rischio è una variabile che si pensa possa avere influenza sull'insorgenza malattia. Quest'ultima, invece, non ha bisogno di commenti: c'è o non c'è. Ovviamente si può anche considerare il verificarsi di un altro fenomeno che non sia necessariamente una malattia, ad esempio il superamento del livello di colesterolo nel sangue (superato o non superato).
In maniera perfettamente analoga, il fattore di rischio potrebbe essere la somministrazione di un farmaco (presente=somministrato, assente= non somministrato o placebo), e quindi potremmo essere interessati a valutare, o meglio a testare il farmaco come fattore di guarigione dalla malattia, o al contrario come fattore di insorgenza di effetti collaterali. Insomma, trattasi di variabile dicotomiche: uno o zero sia per la variabile antecedente che per quella conseguente.
Nella tabella ho utilizzato le lettere a, b , c , d per specificare la numerosità dei casi. Quindi a è il numero di individui in cui è presente il fattore di rischio e la malattia è insorta, ecc.... (la spiegazione del significato delle altre lettere mi pare banale).
L'utilizzo dei dati contenuti in tale tabella dipende sostanzialmente dalle modalità di raccolta dati, ossia dalla distinzione tra indagini prospettiche o longitudinali e indagine retrospettive o trasversali. In realtà questa mia classificazione non è assolutamente esaustiva per le varie situazioni che si presentano in Medicina, ma lo è ai fini del calcolo di un Odds Ratio.
In un indagine prospettica il ricercatore dispone di un gruppo di individui già classificati a seconda del fattore di rischio: un gruppo in cui è presente, un altro in cui non lo è. Lui si "limita" a seguirli nel tempo e a verificare l'insorgenza (Sì) o meno (No) della malattia. In maniera analoga, per testare un farmaco, si disporrà di un gurppo di individui a cui viene somministrato il farmaco contro un placebo. Quindi, in genere, quando parte l'indagine il ricercatore conosce a+b e c+d, mentre conoscerà la scomposizione in a, b, c e d solo successivamente, in base appunto all'insorgenza della malattia. E' molto utile la seguente illustrazione per rappresentare un'indagine prospettica o longitudinale:














Dall'immagine si evince anche il perché si parla di indagine longitudinale: se si guarda un mappamondo, la longitudine è una linea orizzontale, proprio come la freccia (una barbara definizione che rende l'idea). La figura mette in risalto i dati disponibili a priori dal ricercatore: a+b e c+d e nel tempo potrà poi suddividere i dati in base all'insorgenza della malattia.
In un'indagine retrospettiva, invece, accade esattamente il contrario. Il ricercatore dispone degli individui già classificati in base all'insorgenza della malattia e lo scopo della sua indagine è procedere a "ritroso" per risalire al fattore di rischi e quindi classificare in soggetti con o senza fattore di rischio. Un classico esempio è un gruppo di malati di tumore (insorgenza malattia: Sì) ed uno di sani (insorgenza malattia: No) ai quali viene chiesto se in passato hanno fumato (fattore di rischio: presente) o meno (fattore di rischio: assente). Si deduce facilmente che si può rappresentare l'indagine retrospettiva nel seguente modo:
















Il ricercatore, quindi, conosce a priori a+c e b+d e solo dopo l'indagine potrà risalire all'eventuale presenza del fattore di rischio.
A questo punto è abbastanza semplice scegliere un indice che spieghi il meglio possibile la relazione tra le due variabili dicotomiche rappresentate in tabella.
Nel caso di indagine prospettica, è intuitivo procedere al calcolo della probabilità che insorga la malattia, distinguendo in base all'appartenenza ad uno dei due gruppi:
1- probabilità che insorga la malattia in un individuo esposto al fattore di rischio: pr(Sì \ presente) = a / (a+b);
2- probabilità che insorga la malattia in un individuo non esposto al fattore di rischio: pr(Sì \ assente) = c / (c+d) .
Come giè spiegato prima, in un'indagine longitudinale è logico costruire questi due indici. Il ricercatore, infatti, dispone dei due campioni (a+b e c+d) prima di inziare l'indagine e solo successivamente osserva il fenomeno di insorgenza malattia. Confrontando semplicemente il rapporto 1 con il rapporto 2 tenterà di rispondere alla domanda: il fattore di rischio aumenta significativamente la probabilità che si presenti la malattia? E' ovvio che siamo portati a dare risposta affermativa quanto più la prima probabilità è maggiore della seconda. Ovviamente questo ragionamento sarà un po' più complicato in quanto accompagnato da un insieme di strumenti statistici sui quali non mi soffermo (verifica di ipotesi, modelli logit, ecc....).
In Epidemiologia si è soliti parlare di rischio assoluto invece che di probabilità, quindi il medico e lo statistico cercheranno di valutare se il rischio di tipo 1 è maggiore del rischio di tipo 2. La valutazione di questo semplice aspetto può avvenire rapportando il rischio o probabilità 1 al rischio o probabilità 2. Quanto più tale rapporto sarà maggiore di 1, tanto più saremo portati a pensare che il rischio di insorgenza malattia sia più forte se il fattore di rischio è presente. Tal rapporto viene detto rischio relativo:


a /(a+b) / c/(c+d).


A questo punto chi ha una forma mentis quantitativa (...proprio come lo statistico...) si divertirà nella ricerca di forme matematiche diverse di tale rapporto, ma io direi che poco interessano e poco servono a chi è interessato alla comprensione del fenomeno. Anzi direi che potrebbero essere addirittura controproducenti, portando il ricercatore a perdere di vista l'obiettivo.
Il caso appena discusso riguarda l'indagine prospettica, vediamo ora cosa accade nell'altro caso.
Nell'indagine retrospettiva abbiamo illustrato chiaramente che a priori non si dispone del campione suddiviso per fattore di rischio, ossia mediante il fattore logicamente antecedente, ma si disporrà dei malati e dei sani. Procedendo "retrospettivamente" alla classificazione in base alla presenza o l'assenza del fattore di rischio (...fumavi in passato?...) si riempirà la tabellina in ognuna delle quattro caselle, ma il calcolo del rischio relativo non ha più senso. La freccia disegnata, infatti, non segue più lo stesso "senso dei dati" (è verticale, non più orizzonatale). I campioni sono ora a+c e b+d, e mischiare a con b e c con d potrebbe portare a risultati fortemente errati. Le numerosità dei due campioni, infatti, saranno in genere molto diverse, con un campione di sani generalmente più grande di quello di malati (b+d > a+c).
Immaginiamo paradossalmente di disporre di 8 malati (a+c) e 200 sani (b+d). Li interroghiamo sulle loro abitudini di vita e scompriamo che degli 8 malati, 3 hanno fumato (quindi a=3) mentre trai i 200 hanno fumato in 150 (b=150). A questo punto ve la sentireste di dire che 3 / (3+150) (ossia il rischio a/a+b) è la probabilità di ammalarsi essendo stati fumatori? Io direi che non ha senso sommare 3 a 150 poiché i dati sono di campioni diversi; non abbiamo mica seguito nel tempo 153 individui fumatori valutando così l'insorgenza della malattia! Essendo errato il calcolo del rischio assoluto e ralativo in tale caso, si usa studiare il fenomeno con l'Odds Ratio.
Innanzitutto, diciamo che un Odds è un rapporto di probabilità. Consideriamo un campione suddiviso in base alla presenza o assenza di una caratteristica, ossia la nostra variabilie dicotomica (maschio/femmina, fumatore/non fumatore, bello/brutto, ecc....). Se a sono i fumatori e c i non fumatori (nel campione di malati) , a / (a+c) è la probabilità di trovare un fumatore nel nostro campione. Analogamente, c / (a+c) è la probabilità di trovare un non fumatore. L'Odds (relativamente ai malati) per tale variabile dicomotica è quindi il rapporto tra la probabilità che una unità del campione sia fumatrice e la probabilità che sia non fumatrice:


a /(a+c) / c/(a+c) = a / c.


Tale indice ci dice quanto è maggiore la probabilità di beccare un fumatore rispetto a quella di non beccarlo. Torniamo alla tabella relativa al caso di un'indagine retrospettiva.
In base a come abbiamo costruito il nostro campione, seguendo la freccia verticale, ha senso calcolare anche l'Odds per i sani:


b/(b+d) / d/(b+d) = b / d.


A questo punto l'Odds Ratio è il rapporto dei due Odds (così come il rischio relativo e il rapporto dei due rischi assoluti):


a/c / b/d.


Se tale valore è maggiore di 1, l'Odds dei malati è maggiore di quello dei sani e quindi potremmo dire che nei malati la probabilità di beccare un fumatore rispetto a quelle di non beccarlo è maggiore rispetto a quanto accade nei sani. Tale modo di ragionare, però, nasconde evidentemente qualcosa di "illogico". E' come se stessimo supponendo l'insorgenza della malattia come variabile antecedente il fattore di rischio, ossia che la malattia influisce sul fattore di rischio, ossia su di una variabile che invece si manifesta "prima" dell'altra. Quello che invece ci interesserebbe verificare è quanto cambia il rapporto tra la probabilità di ammalarsi e non, passando da un gruppo di individui senza fattore di rischio ad individui con fattore di rischio (qualcosa di analogo al rischio relativo).
Mentre per un'indagine prospettiva è subito evidente che possiamo eseguire tale calcolo (seguiamo il senso della freccia), da una prima riflessione potrebbe sembrare errato il calcolo di tale Odds Ratio per un'indagine retrospettiva (così come invece lo sarebbe il calcolo del rischio relativo). Ma con un banale passaggio algebrico si ottiene che:


a/c / b/d = a/b / c/d,


ossia che l'Odds Ratio per la nostra tabella è sempre lo stesso, indipendentemente da quale sia la variabile logicamente antecendente (cosa che invece non accade per il rischio relativo). Non è superfluo evidenziare che il secondo membro dell'uguaglianza è l'Odds Ratio che misura di quanto è più probabile l'insorgenza malattia rispetto alla non insorgenza, passando da individui con fattore di rischio a individui senza tale fattore.
Quindi, riassumendo, la nostra tabella con le quattro caselline è in pratica un campione che si suppone rappresentativo dell'universo. Calcolando uno qualunque degli indici sopra descritti, non facciamo altro che cercare di stimare lo stesso valore ignoto nell'universo. La differenza sostanziale, però, sta nel fatto che mentre il rischio relativo ha senso solo per l'indagine prospettiva, l'Odds Ratio è indipendente dal tipo di indagine. Quindi, il rischio relativo è una buona stima campionaria solo per le indagini retrospettive, mentre l'Odd Ratio lo è in entrambi i casi!
Quindi, per un'indagine retrospettiva useremo l'Odds Ratio per rispondere alla stessa domanda di prima: il fattore di rischio aumenta significativamente la possibilità che si presenti la malattia? Quanto più a/b /c/d sarà >1, tanto più saremo portati a dire che nel passaggio dalla situazione di assenza alla situazione di presenza del fattore di rischio , cresce il rapporto tra la probabilità di ammalarsi e quella che la malattia non insorga.
Sottolineo inoltre che in genere l'Odds Ratio è utilizzato sempre, quindi mi pare sia preferito anche nelle indagine prospettiche, sebbene in tali casi sia possibile calcolare il rischio relativo (ovviamente questa è solo una mia impressione).
Nei più diffusi testi di Epidemiologia o Statistica Medica si è soliti parlare di rapporto crociato in luogo di Odds Ratio. A mio parere tale esemplificazione algebrica è totalmente inutile e addirittura controproducente e per tale motivo nemmeno la riporto. Per quanto riguarda l'aspetto "informatico" per il calco di tali indici, direi che non è necessario nessun commento essendo il processo di calcolo molto banale e facilemente gestibile in un un foglio elettronico.
Concludo dicendo che il ragionamento che ho seguito è utile a comprendere il significato di Odds Ratio e Rischio Relativo, evitando quindi lo sforzo memorico necessario a ricordare i metodi di calcolo dei rapporti (...l'odds è il prodotto della cella a per b, diviso per...). Ovviamente, per completare il tutto, sarebbe necessario approfondire con lo studio della verifica di ipotesi e dei modelli logit, ma tali argomenti sono abbondantemente trattati nei testi di stastica ed anche in rete.

30 settembre 2008

Gestire i Missing Value in R

La visualizzazione e l'imputazione dei "dati mancanti" in un'indagine , in particolare nella Statistica Ufficiale, è sicuramente la fase più importante per garantire la qualità del dato statistico . La letteratura sull'argomento è matura e ben fornita, e i software commerciali non prevedono, a mio parere, un modulo "completo" (ovviamente in ognuno di questi ci sono possibilità di sviluppare grafici ad-hoc e applicare un qualsivoglia test).
In particolare l'ISTAT ha sviluppato in SAS il software
CONCORD per il controllo e la correzione dei dati, strumento potentissimo e liberamente scaricabile, ma che appunto necessita del SAS.
In R esiste la possibilità di lavorare con
VIM, che sta appunto per Visualization and Imputation of Missing values. Come gli stessi autori sottolineano, il cuore del pacchetto sta nell'insieme dei possibili grafici utili alla scoperta e alla gestione dei missing values.
In realtà, analogamente a quanto ho già scritto per
Rcmdr, un altro grande aspetto è la possibilità di ricorrere all'interfaccia grafica (sviluppata mediante il pacchetto tcltk). Non dimentichiamo, infine, le possibilità di integrazione di R con il pacchetto office e la possibilità si sviluppo in maniera estremamente immediata delle interfacce grafiche (ad esempio via Access).
Concludo osservando che l'ISTAT ha già espresso
parere sostanzialmente postivo per l'utilizzo di R ed ha avviato un processo di migrazione a tale strumento...quindi R anche nella statistica ufficiale.