giovedì 11 agosto 2022

Test di Fisher

Quando si effettuano dei conteggi nei quali le osservazioni sono organizzate in una tabella di due righe per due colonne, si applicano queste regole:
si impiega il test chi-quadrato se le osservazioni sono indipendentisono numerose;
si impiega il test di Fisher se le osservazioni sono indipendenti e sono poche;
si impiega il test di McNemar nel caso di osservazioni non indipendenti (cioè nel caso di dati appaiati).

Armitage [1] e Snedecor [2] indicano la necessità di impiegare il test di Fisher (detto anche test esatto di Fisher) in alternativa al test chi-quadrato quando:
→ il numero totale di osservazioni è inferiore a 20;
→ il numero totale di osservazioni è compreso tra 20 e 40 e vi sono frequenze attese inferiori a 5.

Le indicazioni che potete trovare su altri test di statistica sono meno vincolanti sui limiti da applicare al numero totale di osservazioni, mentre concordano tutte nel sottolineare la necessità di applicare il test di Fisher quando in una o più celle vi è un numero ridotto di frequenze attese, le frequenze che dovremmo osservare in teoria e che sono calcolate per ciascuna cella come prodotto delle somme marginali (di riga e di colonna) corrispondenti, diviso per il numero totale dei casi - così ad esempio nella tabella riportata qui sotto per la cella in alto a sinistra contenente il valore osservato 4 la frequenza attesa sarà (4+16) · (4+1) / (4+16+1+21) = 20 · 5 / 42 = 2.38 e per la cella in basso a destra con il valore osservato 21 la frequenza attesa sarà (21+1) · (21+16) / (4+16+1+21) = 22 · 37 / 42 = 19.38

Il test di Fisher lo applichiamo all'analisi della relazione che potrebbe intercorrere (e che vogliamo verificare) tra il tipo di allattamento, naturale o artificiale, e la presenza in età successiva nel bambino di malocclusione dentariaLa suzione da una tettarella in gomma non è del tutto fisiologica e potrebbe determinare un qualche effetto sulla morfogenesi delle arcate dentarie che è in atto nel lattante. I dati sono tratti da [3] e sono riportati in questa tabella che contiene quindi le frequenze osservate:


Questo script prevede di inserire i dati manualmente. Copiatelo e incollatelo nella Console di R e premete ↵ Invio:

# TEST DI FISHER - 2 righe · 2 colonne
#
cells <- c(4,16,1,21) # genera l'array cells con i valori numerici contenuti nelle celle
rnames <- c("Allattamento_naturale", "Allattamento_artificiale") # genera l'array rnames con i nomi delle righe
cnames <- c("Denti_normali", "Malocclusione") # genera l'array cnames con i nomi delle colonne
mydata <- matrix(cells, nrow=2, ncol=2, byrow=TRUE, dimnames=list(rnames, cnames)) # genera la matrice dei dati
mydata # mostra i dati
fisher.test(mydata) # esegue il test di Fisher
#

Nelle prime tre righe sono generati con la funzione c():
il vettore che contiene i quattro dati (che come si vede devono essere inseriti in sequenza leggendoli da sinistra a destra e dall'alto in basso) che sono salvati nell'oggetto cells;
il vettore che contiene i nomi delle righe, salvato nell'oggetto rnames;
il vettore che contiene i nomi delle colonne, salvato nell'oggetto cnames.

I tre vettori sono combinati a formare la matrice dei dati mediante la funzione matrix() che impiega gli argomenti che indicano:
l'oggetto/vettore contenente i dati (cells);
il numero di righe (nrow=2) e il numero di colonne (ncol=2) della matrice che sarà pertanto di due righe per due colonne;
la modalità di riempimento della matrice, che deve essere riempita per righe (byrow=TRUE) quindi da sinistra a destra e dall'alto in basso;
i nomi da assegnare alle righe e alle colonne (dimnames=list(rnames, cnames)).

La matrice dei dati così costruita viene salvata nell'oggetto mydata, che viene infine mostrato per un controllo finale.

Come si vede la parte principale del lavoro consiste nella corretta immissione e strutturazione dei dati, mentre il calcolo vero e proprio del test viene effettuato in modo molto semplice, con la funzione fisher.test() [4].

Questi sono i risultati:

> mydata # mostra i dati 

                         Denti_normali Malocclusione
Allattamento_naturale                4            16
Allattamento_artificiale             1            21
> fisher.test(mydata) # esegue il test di Fisher

        Fisher's Exact Test for Count Data

data:  mydata
p-value = 0.1745
alternative hypothesis: true odds ratio is not equal to 1
95 percent confidence interval:
   0.4440411 270.1636947
sample estimates:
odds ratio 
  5.059936 

Considerando significativi i valori inferiori al tradizionale valore soglia p = 0.05 il test di Fisher fornisce nel nostro caso come risultato un valore di p = 0.1745 che non è significativo: pertanto la conclusione è che non abbiamo evidenza statistica del fatto che i due tipi di allattamento comportino differenze nella prevalenza di malocclusione.

La funzione fisher.test() fornisce una analisi aggiuntiva della tabella calcolando anche l'odds ratio. In questo caso un risultato diverso da 1 deporrebbe per una associazione tra tipo di allattamento e tipo di occlusione dentaria. Un risultato diverso da 1 si avrebbe se i limiti di confidenza dell'odds ratio trovato, che è uguale a 5.059936, non includessero il valore 1. Dato che lo includono (vanno infatti da 0.4440411 a 270.1636947) il risultato non è significativo, conferma la mancanza di associazione tra i fattori presenti nella tabella e conferma anche il valore di p ottenuto con il test di Fisher. Per il tema odds ratio si rimanda ai test di statistica: si trova tra gli altri in Marubini [5], Campbell [6] e Ingelfinger [7].

Abbiamo qui una tipica applicazione del buonsenso in statistica: con un numero totale di osservazioni superiore a 40 (sono in totale 42 osservazioni) avremmo dovuto a rigore applicare il test chi-quadrato, ma è stato applicato il test di Fisher in quanto è stato dato maggior peso al fatto che vi sono celle con un numero ridotto di osservazioni. A conferma di ciò potete eseguire il test chi-quadrato digitando

chisq.test(mydata)

con questo risultato:

> chisq.test(mydata)

        Pearson's Chi-squared test with Yates' continuity correction

data:  mydata
X-squared = 1.1398, df = 1, p-value = 0.2857

Messaggio di avvertimento:
In chisq.test(mydata) : Chi-squared approximation may be incorrect

Il test chi-quadrato indica una non significatività nelle differenze (p = 0.2857) ma un messaggio avverte che l'impiego del test chi-quadrato in questo caso non è appropriato. La ragione? Se digitate

chisq.test(mydata)$expected

ottenete la tabella delle frequenze attese

> chisq.test(mydata)$expected
                         Denti_normali Malocclusione
Allattamento_naturale         2.380952      17.61905
Allattamento_artificiale      2.619048      19.38095
Messaggio di avvertimento:
In chisq.test(mydata) : Chi-squared approximation may be incorrect

nella quale notate sulla sinistra due valori inferiori a 5. Il messaggio "Chi-squared approximation may be incorrect" viene fornito dalla funzione chisq.test() in quanto anche in R la regola "frequenze attese inferiori a 5" rappresenta il razionale per l'impiego del test di Fisher e prevale sul numero delle osservazioni.

In alternativa potete procedere come segue.

Copiate le tre righe riportate qui sotto, incollatele in un editor di file di testo aggiungendo un ↵ Invio al termine dell'ultima riga, e salvate il tutto in C:\Rdati\ sotto forma di un file di testo denominato chi_Fisher.csv (di default i file di testo sono salvati con l'estensione .txt ma noi qui salviamo il file con l'estensione .csv) [8].

Allattamento;Denti_normali;Malocclusione
Allattamento_naturale;4;16
Allattamento_artificiale;1;21

Impiegate quest'altro script che prevede di eseguire il test di Fisher sui dati letti dal file chi_Fisher.csv precedentemente salvato. Copiatelo e incollatelo nella Console di R e premete ↵ Invio:

# TEST DI FISHER - 2 righe · 2 colonne 
#
mydata <- read.table("C:/Rdati/chi_Fisher.csv", header=TRUE, sep=";", row.names="Allattamento") # importa i dati
mydata # mostra i dati
fisher.test(mydata) # esegue il test di Fisher
#

Come vedete lo script è più compatto del precedente, le uniche cose da notare sono gli argomenti della funzione read.table():
"C:/Rdati/chi_Fisher.csv" che specifica nome e posizione del file dal quale importare i dati;
header=TRUE che indica che nella prima riga del file sono contenuti i nomi delle variabili;
sep=";" che specifica il separatore di campo impiegato nel file;
row.names="Allattamento" che indica che i nomi delle righe sono contenuti nel campo “Allattamento”.

Salvate entrambi gli script. Se preferite intervenire sullo script per adattarlo di volta in volta ai nuovi dati, potete impiegare il primo dei due. Se volete evitare di mettere mano ogni volta allo script e preferite intervenire sul file di dati, potete impiegare il secondo.


----------

[1] Armitage P. Statistica medica. Giangiacomo Feltrinelli Editore, MIlano, 1979, p.140.

[2] Snedecor GW, Cochran WG. Statistical Methods. The Iowa State University Press, 1980, ISBN 0-8138-1560-6, p. 127.

[3] Armitage P. Statistica medica. Giangiacomo Feltrinelli Editore, MIlano, 1979, pp. 138-140.

[4] Digitate help(fisher.test) nella Console di R per la documentazione della funzione fisher.test().

[5] Bossi A, Cortinovis I, Duca PG, Marubini E. Introduzione alla statistica medica. La Nuova Italia Scientifica, Roma, 1994, ISBN 88-430-0284-8, pp. 282-285.

[6] Campbell MJ, Machin D. Medical Statistics. A Commonsense Approach. John Wiley & Sons, New York, 1993, ISBN 0-471-93764-9, pp. 121-123 e 154-156.

[7] Ingelfinger JA, Mosteller F, Thibodeau LA, Ware JH. Biostatistica in medicina. Macmillan Publishing Co., Inc.; New York, 1983, ISBN 88-7078-065.1, pp. 30-33.

[8] Per eventuali approfondimenti sul formato .csv (comma separated value) che è il formato dati raccomandato per R vedere i post nella sezione R - gestione dati della pagina Indice.