Una tabella di contingenza riassume la distribuzione congiunta di due variabili qualitative, riportando le frequenze (assolute o relative) per ciascuna combinazione di modalità . Le righe corrispondono alle modalità di una variabile (\(X\)), le colonne alle modalità dell’altra (\(Y\)).
I dati riguardano una ricerca sulla diffusione del melanoma maligno rispetto al tipo di tumore (\(X\)) e al luogo di insediamento (\(Y\)):
| Variabile | ModalitĂ |
|---|---|
| \(X\) — Tipo di tumore | efelidi melanotiche, melanoma sparso, nodulare, indeterminato |
| \(Y\) — Luogo di insediamento | testa e collo, tronco, estremità |
Leggiamo il file tumore.dat. I dati sono giĂ riportati
in forma di tabella di contingenza.
đź’ˇ Per utilizzare le funzioni per le tabelle il data frame deve essere convertito in matrice
tumore <- read.table("tumore.dat",
header = TRUE,
row.names = 1,
sep = "&")
m_tumore <- as.matrix(tumore)La distribuzione congiunta di \((X, Y)\) descrive la frequenza (assoluta o relativa) di ogni coppia di modalitĂ \((i, j)\). In R, possiamo visualizzare
le frequenze assolute usando table() (ma in questo
caso sono giĂ letti in forma tabellare)
le frequenze relative usando prop.table() applicata
a una tabella
#> testa.collo tronco estremita
#> efelidi.melanot. 22 2 10
#> melanoma.sparso 16 54 115
#> nodulare 19 33 73
#> indeterminato 11 17 28
#> testa.collo tronco estremita
#> efelidi.melanot. 5.50 0.50 2.50
#> melanoma.sparso 4.00 13.50 28.75
#> nodulare 4.75 8.25 18.25
#> indeterminato 2.75 4.25 7.00
Le distribuzioni marginali si ottengono sommando le frequenze lungo una dimensione della tabella. In formule,
\(n_{j\cdot} = \sum_{k=1}^{K} n_{jk}\) e \(n_{\cdot k} = \sum_{j=1}^{J} n_{jk}\)
\(\sum_{j=1}^{J}n_{j\cdot} = n\) e \(\sum_{k=1}^{K}n_{\cdot k} = n\)
\[ \begin{array}{c|cccc|c} & 1 & 2 & \cdots & K & \text{Totale} \\ \hline 1 & n_{11} & n_{12} & \cdots & n_{1K} & n_{1\cdot} \\ 2 & n_{21} & n_{22} & \cdots & n_{2K} & n_{2\cdot} \\ \vdots & \vdots & \vdots & \ddots & \vdots & \vdots \\ J & n_{J1} & n_{J2} & \cdots & n_{JK} & n_{J\cdot} \\ \hline \text{Totale} & n_{\cdot 1} & n_{\cdot 2} & \cdots & n_{\cdot K} & n \end{array} \]
Da cui possiamo ottenere le frequenze relative marginali di riga e colonna
In R, otteniamo con margin.table(m, 1) somma per riga
(distribuzione di \(X\)), mentre con
margin.table(m, 2) somma per colonna (distribuzione di
\(Y\)). Le frequenze relative si
ottengono utilizzando prop.table() alle frequenze assolute
marginali.
# Marginale di X (tipo di tumore) — somma per riga
margine_riga_ass <- margin.table(m_tumore, 1)
margine_riga_ass#> efelidi.melanot. melanoma.sparso nodulare
#> 34 185 125
#> indeterminato
#> 56
#> efelidi.melanot. melanoma.sparso nodulare
#> 8.5 46.2 31.2
#> indeterminato
#> 14.0
# Marginale di Y (luogo di insediamento) — somma per colonna
margine_colonna_ass <- margin.table(m_tumore, 2)
margine_colonna_ass#> testa.collo tronco estremita
#> 68 106 226
#> testa.collo tronco estremita
#> 17.0 26.5 56.5
Utilizziamo il grafico a barre, barplot() per
reppresentare le frequenze relative marginali (di riga: tipo di tumore;
e di colonna: luogo di insediamento).
par(mfrow = c(2, 1))
barplot(margine_riga_rel, ylim = c(0, 1),
main = "Tipo di tumore (X)",
ylab = "Frequenza relativa",
col = c("#D4A574", "#8B3A3A", "#5B4A72", "#6B8E8E"))
abline(h = 0)
barplot(margine_colonna_rel, ylim = c(0, 1),
main = "Luogo di insediamento (Y)",
ylab = "Frequenza relativa",
col = c("#4A7FA5", "#6AAF8B", "#C47E5A"))
abline(h = 0)đź’ˇ Il comando
par()serve per settare alcuni parametri della finestra grafica: in questo caso l’argomentomfrow = c(2,1)divide la finestra grafica in due colonne e una riga.
Uno studio completo di due variabili qualitative richiede di esaminare il comportamento di una variabile all’interno dei gruppi definiti dall’altra. A questo scopo si relativizzano le frequenze congiunte rispetto al totale di riga.
La frequenza relativa di \(Y = k\) condizionata a \(X = j\) è:
\[f_{k|j} = \frac{n_{jk}}{n_{j\cdot}} = \frac{f_{jk}}{f_{j\cdot}}\]
L’insieme di queste frequenze al variare di \(k\) costituisce il profilo riga della categoria \(j\).
💡 La distribuzione marginale è anche chiamata profilo medio dell’intera popolazione.
Al fine di calcolare i profili riga si usa il comando
prop.table() utilizzando come aromento
margin = 1.
profili_riga <- prop.table(m_tumore, margin = 1) # relativizza per riga
rbind(round(profili_riga * 100, 1),
round(margine_colonna_rel * 100, 1))#> testa.collo tronco estremita
#> efelidi.melanot. 64.7 5.9 29.4
#> melanoma.sparso 8.6 29.2 62.2
#> nodulare 15.2 26.4 58.4
#> indeterminato 19.6 30.4 50.0
#> 17.0 26.5 56.5
📌 Confrontiamo ad esempio gli insediamenti in testa e collo: il tipo “efelidi melanotiche” presenta il 64.7% degli insediamenti in questa zona, contro il 17% della distribuzione marginale complessiva. Il tipo “melanoma sparso” invece si insedia prevalentemente alle estremità (62.2%).
Per confrontare i profili riga graficamente possiamo procedere nei seguenti modi.
Riportiamo le distribuzioni di luogo di insediamento condizionate al
tipo di tumore mediante barplot affiancati. In questo caso è importante
mantenere la stessa scala sull’asse delle ordinate
(ylim = c(0,1)), altrimenti le differenze visive risultano
fuorvianti.
par(mfrow = c(2, 3))
for (i in 1:nrow(profili_riga)) {
barplot(profili_riga[i, ],
ylim = c(0, 1),
main = rownames(profili_riga)[i],
ylab = "Frequenza relativa",
col = c("#4A7FA5", "#6AAF8B", "#C47E5A"))
abline(h = 0)
}
# Profilo marginale (totale) come riferimento
barplot(margine_colonna_rel,
ylim = c(0, 1),
main = "Totale (profilo medio)",
ylab = "Frequenza relativa",
col = c("#4A7FA5", "#6AAF8B", "#C47E5A"))
abline(h = 0)
par(mfrow = c(1, 1))📌 Si osserva chiaramente che la distribuzione del luogo di insediamento per il tipo “efelidi melanotiche” è significativamente diversa da quelle degli altri tre tipi e dal profilo medio complessivo: oltre il 60% degli insediamenti avviene in testa e collo, contro il 17% del totale.
mat <- rbind(profili_riga, Totale = margine_colonna_rel)
barplot(t(mat),
beside = F,
col = c("#4A7FA5", "#6AAF8B", "#C47E5A"),
ylim = c(0,1.3),
ylab = "Frequenza relativa",
main = "Profili riga e marginale (di colonna)",
cex.names = 0.5,
legend.text = colnames(mat))📌 Le informazioni lette mediante barplot affiancati sono di più facile lettura mediante barplot impilati, ovvero è chiaro che la distribuzione del luogo di insediamento per il tipo “efelidi melanotiche” differisce da quelle degli altri tre tipi e dal profilo medio complessivo.
Per evidenziare quanto ogni profilo riga si discosti dalla distribuzione marginale si calcolano le deviazioni:
\[\left(f_{1|j} - f_{\cdot 1},\; f_{2|j} - f_{\cdot 2},\; \ldots,\; f_{K|j} - f_{\cdot K}\right)\]
# Costruiamo una matrice con il profilo marginale replicato per ogni riga
tab_margine_colonna_rel <- matrix(
rep(margine_colonna_rel, nrow(m_tumore)),
byrow = TRUE,
ncol = ncol(m_tumore)
)
deviazioni_riga <- profili_riga - tab_margine_colonna_rel
round(deviazioni_riga * 100, 1)#> testa.collo tronco estremita
#> efelidi.melanot. 47.7 -20.6 -27.1
#> melanoma.sparso -8.4 2.7 5.7
#> nodulare -1.8 -0.1 1.9
#> indeterminato 2.6 3.9 -6.5
Quindi rappresentiamo le deviazioni mediante barplot affiancati (uno per ogni modalitĂ di tipo di tumore)
yl <- c(min(deviazioni_riga), max(deviazioni_riga))
par(mfrow = c(2, 2), oma = c(0, 0, 2, 0))
for (i in 1:nrow(profili_riga)) {
barplot(deviazioni_riga[i, ],
ylim = yl,
main = rownames(profili_riga)[i],
ylab = "Deviazione",
col = c("#4A7FA5", "#6AAF8B", "#C47E5A"))
abline(h = 0)
}📌 Le deviazioni confermano e rendono ancora più evidente quanto già osservato nei profili riga:
- Efelidi melanotiche: fortissima sovra-rappresentazione in testa e collo (+47.7%) e sotto-rappresentazione in tronco e estremitĂ
- Melanoma sparso: sotto-rappresentazione in testa e collo (-8.4%), sovra-rappresentazione alle estremitĂ (+5.7%)
- Nodulare e indeterminato: deviazioni contenute, vicini al profilo medio
Si continui l’analisi considerando le le frequenza relativa di \(X = j\) condizionata a \(Y = k\) è:
\[f_{j|k} = \frac{n_{jk}}{n_{\cdot k}} = \frac{f_{jk}}{f_{\cdot k}}\]
L’insieme di queste frequenze al variare di \(j\) costituisce il profilo colonna della categoria \(k\). Quindi le deviazioni dei Profili Colonna dal Profilo Medio (di riga) sono
\[\left(f_{1|k} - f_{\cdot 1},\; f_{2|k} - f_{\cdot 2},\; \ldots,\; f_{J|k} - f_{\cdot k}\right)\]
Si riportano le analisi numeriche e grafiche rilevanti per descrivere la distribuzione del tipo di tumore per luogo di insediamento. Si commentino i risultati.
table() frequnze assolute congiunteprop.table(m) → frequenze relative congiunte (diviso
per il totale)prop.table(m, margin = 1) → profili
riga (ogni riga somma a 1)prop.table(m, margin = 2) → profili
colonna (ogni colonna somma a 1)margin.table(m, 1) → marginale di riga;
margin.table(m, 2) → marginale di colonna# CREAZIONE MATRICE DA DATI
m <- as.matrix(df) # se df è in forma tabellare
# FREQUENZE
prop.table(m) # relative congiunte
prop.table(m, 1) # profili riga
prop.table(m, 2) # profili colonna
margin.table(m, 1) # marginale di riga (assoluta)
margin.table(m, 2) # marginale di colonna (assoluta)
# GRAFICI
barplot(x, ylim = c(0,1), main = "...", ylab = "...")
abline(h = y0) # linea orizzontale
abline(v = x0) # linea verticale
# LAYOUT
par(mfrow = c(r, c)) # griglia r Ă— c di grafici
par(mfrow = c(1,1)) # ripristina layout singolo