Visualizzazione post con etichetta chi-quadrato. Mostra tutti i post
Visualizzazione post con etichetta chi-quadrato. Mostra tutti i post

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).

Quindi bisogna intendersi su cosa significano "numerose" e "poche". 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 in termini di numerosità delle 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 e 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 
 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 significativamente diverso da 1 deporrebbe per una associazione tra tipo di allattamento e tipo di occlusione dentaria. E 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 riporta una differenza non significativa (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 la sezione Gestione dei dati nella pagina Indice.

sabato 8 dicembre 2018

Test chi-quadrato n righe · n colonne

Il test chi-quadrato può essere nella sua forma più generale esteso a n righe · n colonne. Il problema è che più sono le righe e le colonne e più è difficile individuare il valore (o i valori) che contribuiscono a rendere eventualmente significative le differenze. Per questa ragione in genere le tabelle con più righe e più colonne sono scomposte in tabelle più piccole al fine di valutare meglio i contributi dei valori osservati: per questo tipo di analisi, piuttosto delicata, si rimanda ai testi di statistica.

Qui riporto un esempio di una tabella di 2 righe per 5 colonne tratto da Marubini [1] nella quale si riesce a individuare senza troppe complicazioni il risultato che contribuisce a rendere significativa la differenza tra le frequenze osservate.

Si trattava di valutare l'efficacia di cinque differenti vaccini influenzali. I vaccini vennero inoculati a novembre in 1080 soggetti sani volontari e nel mese di marzo dell'anno successivo vennero contati i casi di influenza tra i vaccinati.

Questi erano stati i risultati della sperimentazione. Da notare che viene riportato il numero dei casi cioè il conteggio dei soggetti affetti da influenza e non affetti da influenza, come richiesto dal test chi-quadrato, nel quale invece non devono mai essere riportati i dati espressi in percentuale:

Esito
Vaccino_1
Vaccino_2
Vaccino_3
Vaccino_4
Vaccino_5
Influenza_si
39
44
20
41
42
Influenza_no
177
166
200
183
168

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

# TEST CHI-QUADRATO - n righe · n colonne
#
cells <- c(39, 44, 20, 41, 42, 177, 166, 200, 183, 168) # genera l'array cells con il numero dei casi
rnames <- c("Influenza_si", "Influenza_no") # genera l'array rnames con i nomi delle righe
cnames <- c("Vaccino_1", "Vaccino_2", "Vaccino_3", "Vaccino_4", "Vaccino_5") # genera l'array cnames con i nomi delle colonne
mydata <- matrix(cells, nrow=2, ncol=5, byrow=TRUE, dimnames=list(rnames, cnames)) # genera la matrice dati
mydata # mostra i dati
chisq.test(mydata) # calcola il chi-quadrato
#

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) e il numero di colonne (ncol) della matrice;
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 viene salvata nell'oggetto mydata, che viene mostrato per un ovvio controllo della corretta immissione e strutturazione dei dati.

Infine con la funzione chisq.test() [2] viene effettuato il calcolo del test.

Questi sono i risultati:

> mydata # mostra i dati
             Vaccino_1 Vaccino_2 Vaccino_3 Vaccino_4 Vaccino_5
Influenza_si        39        44        20        41        42
Influenza_no       177       166       200       183       168
> chisq.test(mydata) # calcola il chi-quadrato

        Pearson's Chi-squared test

data:  mydata
X-squared = 13.678, df = 4, p-value = 0.008395

Il test chi-quadrato riporta un valore elevato della statistica chi-quadrato (13.678) cui corrisponde un valore di probabilità p = 0.008395 che conferma quindi la presenza di una differenza significativa nell'efficacia dei vaccini.

In alternativa potete anche copiare le tre righe riportate qui sotto aggiungendo un ↵ Invio al termine dell'ultima riga e salvarle in C:\Rdati\ nel file di testo denominato chi_rxc.csv (attenzione all'estensione al momento del salvataggio del file).

Esito;Vaccino_1;Vaccino_2;Vaccino_3;Vaccino_4;Vaccino_5
Influenza_si;39;44;20;41;42
Influenza_no;177;166;200;183;168

Questo script prevede di eseguire il test chi-quadrato sui dati letti dal file chi_rxc.csv. Copiatelo e incollatelo nella Console di R e premete ↵ Invio:

# TEST CHI-QUADRATO - n righe · n colonne
#
mydata <- read.table("C:/Rdati/chi_rxc.csv", header=TRUE, sep=";", row.names="Esito") # importa i dati
mydata # mostra i dati
chisq.test(mydata) # calcola il chi-quadrato
#

Come vedete lo script è più compatto del precedente, le uniche cose da notare sono gli argomenti della funzione read.table():
"C:/Rdati/chi_rxc.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="Esito" che indica che i nomi delle righe sono contenuti nel campo “Esito”.

Anche se ovviamente i risultati sono sempre gli stessi, il senso di queste due alternative è semplice. Se vi va bene intervenire ogni volta sullo script per adattarlo a nuovi dati, potete impiegare la prima. Potete invece impiegare la seconda se volete evitare di mettere mano ogni volta allo script, e preferite intervenire solamente sul file di dati. A voi la scelta, magari dopo averle sperimentate entrambe.

Se riprendiamo i casi osservati (Influenza_si / Influenza_no) e li trasformiamo in percentuale

Esito
Vaccino_1
Vaccino_2
Vaccino_3
Vaccino_4
Vaccino_5
Influenza_si
18.1
21.0
9.1
18.3
20.0
Influenza_no
81.9
79.0
90.8
81.7
80.0

vediamo che l'eterogeneità dei risultati evidenziata dal test chi-quadrato è da attribuire al vaccino 3, con il quale si è avuto nei vaccinati un tasso di malattia del 9.1%, a fronte di un tasso di malattia omogeneo e praticamente doppio, che va dal 18.1% al 21.0%, che si è avuto nei soggetti vaccinati con gli altri quattro vaccini.


Un utile complemento all'analisi dei dati può essere realizzato mediante la loro rappresentazione grafica dei dati sotto forma di grafico a barre affiancate e grafico a barre sovrapposte.


----------

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

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

[3] Digitate help(barplot) nella Console di R per la documentazione della funzione barplot().

venerdì 7 dicembre 2018

Test di McNemar

Quando le osservazioni sono organizzate in una tabella di 2 righe · 2 colonne si applica questa regola:
si impiega il test chi-quadrato se le osservazioni sono indipendenti e sono 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 dati appaiati). 

Un esempio tipico di applicazione del test di McNemar lo abbiamo in uno studio clinico nel quale lo stesso soggetto viene esposto in tempi diversi a due trattamenti differenti, secondo una sequenza casuale, garantendo che né il paziente né l'operatore sanitario sappiano quale è il trattamento effettuato in quella fase. In questo modo tutti i soggetti, ignorando ogni volta di quale trattamento si tratti, ricevono tutti e due i trattamenti.

Campbell [1] riporta i risultati di uno studio nel quale 250 pazienti sofferenti di artrite erano stati sottoposti ciascuno sia al trattamento con il farmaco A sia al trattamento con il farmaco B. Era stato poi rilevato il grado di soddisfazione dei pazienti rispetto all'uno e all'altro trattamento, con i risultati qui riportati:


In totale 150 soggetti si erano mostrati soddisfatti di entrambi i trattamenti, 50 avevano espresso insoddisfazione per entrambi, mente altri 50 si erano mostrati insoddisfatti chi dell'uno e chi dell'altro.

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

# TEST DI MCNEMAR - 2 righe · 2 colonne
#
cells <- c(150, 20, 30, 50) # genera l'array cells con i valori numerici contenuti nelle celle
rnames <- c("Soddisfatto_da_B", "Non_soddisfatto_da_B") # genera l'array rnames con i nomi delle righe
cnames <- c("Soddisfatto_da_A", "Non_soddisfatto_da_A") # 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
mcnemar.test(mydata, correct=TRUE) # esegue il test di McNemar
#

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) e il numero di colonne (ncol) della matrice;
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 viene salvata nell'oggetto mydata, che viene mostrato per un ovvio controllo della corretta immissione e strutturazione dei dati.

Infine con la funzione mcnemar.test() [2] viene effettuato il calcolo del test. Da notare che anche nel test di McNemar, che è di fatto una statistica chi-quadrato, viene applicata la correzione di Yates per la continuità [3] ponendo l'argomento correct=TRUE

Questi sono i risultati

> mydata # mostra i dati 
                     Soddisfatto_da_A Non_soddisfatto_da_A
Soddisfatto_da_B                  150                   20
Non_soddisfatto_da_B               30                   50
> matrix <- data.matrix(mydata) # viene generato l'oggetto matrice richiesto dalla fase successiva
> mcnemar.test(matrix, correct=TRUE) # esegue il test di McNemar

        McNemar's Chi-squared test with continuity correction

data:  matrix
McNemar's chi-squared = 1.62, df = 1, p-value = 0.2031

che dimostrano che la differenza tra i gradi di soddisfazione espressi dai pazienti in merito ai due trattamenti non è significativa (p = 0.2031).

In alternativa potete anche copiare le tre righe riportate qui sotto aggiungendo un ↵ Invio al termine dell'ultima riga e salvarle in C:\Rdati\ nel file di testo denominato chi_McNemar.csv (attenzione all'estensione al momento del salvataggio del file).

Esito;Soddisfatto_da_A;Non_soddisfatto_da_A
Soddisfatto_da_B;150;20
Non_Soddisfatto_da_B;30;50

Questo script prevede di eseguire il test di McNemar sui dati letti dal file chi_McNemar.csv. Copiatelo e incollatelo nella Console di R e premete ↵ Invio:

# TEST DI MCNEMAR - 2 righe · 2 colonne
#
mydata <- read.table("C:/Rdati/chi_McNemar.csv", header=TRUE, sep=";", row.names="Esito") # importa i dati
mydata # mostra i dati
matrix <- data.matrix(mydata) # viene generato l'oggetto matrice richiesto dalla fase successiva
mcnemar.test(matrix, correct=TRUE) # esegue il test di McNemar
#

Come vedete lo script è più compatto del precedente, le uniche cose da notare sono gli argomenti della funzione read.table():
"C:/Rdati/chi_McNemar.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="Esito" che indica che i nomi delle righe sono contenuti nel campo “Esito”.

Anche se ovviamente i risultati sono sempre gli stessi, il senso di queste due alternative è semplice. Se vi va bene intervenire ogni volta sullo script per adattarlo a nuovi dati, potete impiegare la prima. Potete invece impiegare la seconda se volete evitare di mettere mano ogni volta allo script, e preferite intervenire solamente sul file di dati. A voi la scelta, magari dopo averle sperimentate entrambe.

La rappresentazione grafica dei dati può essere effettuata mediante un grafico a barre.



----------

[1] Campbell MJ, Machin D. Medical Statistics. A Commonsense Approach. John Wiley & Sons, New York, 1993, ISBN 0-471-93764-9, pp. 148-150.

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