Questo progetto analizza i dati di 2.500 nascite raccolte da tre ospedali, con l’obiettivo di studiare i fattori associati al peso alla nascita e costruire un modello per stimarlo.
L’analisi comprende una prima esplorazione dei dati, alcuni test statistici, un modello di regressione lineare multipla e una previsione applicata a un caso specifico.
I risultati saranno interpretati in modo semplice, tenendo conto anche dei limiti dell’analisi.
Per iniziare, carico il dataset e controllo le dimensioni, le variabili e la presenza di valori mancanti.
# Carico i dati
dati <- read.csv("neonati.csv")
# Controllo la struttura e le dimensioni
dim(dati)
## [1] 2500 10
str(dati)
## 'data.frame': 2500 obs. of 10 variables:
## $ Anni.madre : int 26 21 34 28 20 32 26 25 22 23 ...
## $ N.gravidanze: int 0 2 3 1 0 0 1 0 1 0 ...
## $ Fumatrici : int 0 0 0 0 0 0 0 0 0 0 ...
## $ Gestazione : int 42 39 38 41 38 40 39 40 40 41 ...
## $ Peso : int 3380 3150 3640 3690 3700 3200 3100 3580 3670 3700 ...
## $ Lunghezza : int 490 490 500 515 480 495 480 510 500 510 ...
## $ Cranio : int 325 345 375 365 335 340 345 349 335 362 ...
## $ Tipo.parto : chr "Nat" "Nat" "Nat" "Nat" ...
## $ Ospedale : chr "osp3" "osp1" "osp2" "osp2" ...
## $ Sesso : chr "M" "F" "M" "M" ...
summary(dati)
## Anni.madre N.gravidanze Fumatrici Gestazione
## Min. : 0.00 Min. : 0.0000 Min. :0.0000 Min. :25.00
## 1st Qu.:25.00 1st Qu.: 0.0000 1st Qu.:0.0000 1st Qu.:38.00
## Median :28.00 Median : 1.0000 Median :0.0000 Median :39.00
## Mean :28.16 Mean : 0.9812 Mean :0.0416 Mean :38.98
## 3rd Qu.:32.00 3rd Qu.: 1.0000 3rd Qu.:0.0000 3rd Qu.:40.00
## Max. :46.00 Max. :12.0000 Max. :1.0000 Max. :43.00
## Peso Lunghezza Cranio Tipo.parto
## Min. : 830 Min. :310.0 Min. :235 Length:2500
## 1st Qu.:2990 1st Qu.:480.0 1st Qu.:330 Class :character
## Median :3300 Median :500.0 Median :340 Mode :character
## Mean :3284 Mean :494.7 Mean :340
## 3rd Qu.:3620 3rd Qu.:510.0 3rd Qu.:350
## Max. :4930 Max. :565.0 Max. :390
## Ospedale Sesso
## Length:2500 Length:2500
## Class :character Class :character
## Mode :character Mode :character
##
##
##
# Controllo i valori mancanti
colSums(is.na(dati))
## Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza
## 0 0 0 0 0 0
## Cranio Tipo.parto Ospedale Sesso
## 0 0 0 0
Il dataset non presenta valori mancanti, ma alcune variabili hanno valori che potrebbero essere errati. Controllo quindi le osservazioni sospette e le categorie presenti.
# Controllo i valori sospetti
dati[dati$Anni.madre < 12 | dati$Anni.madre > 55, ]
## Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio
## 1152 1 1 0 41 3250 490 350
## 1380 0 0 0 39 3060 490 330
## Tipo.parto Ospedale Sesso
## 1152 Nat osp2 F
## 1380 Nat osp3 M
dati[dati$Gestazione < 22 | dati$Gestazione > 44, ]
## [1] Anni.madre N.gravidanze Fumatrici Gestazione Peso
## [6] Lunghezza Cranio Tipo.parto Ospedale Sesso
## <0 righe> (o 0-length row.names)
dati[dati$Peso < 500 | dati$Peso > 6000, ]
## [1] Anni.madre N.gravidanze Fumatrici Gestazione Peso
## [6] Lunghezza Cranio Tipo.parto Ospedale Sesso
## <0 righe> (o 0-length row.names)
dati[dati$Lunghezza < 350 | dati$Lunghezza > 600, ]
## Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio
## 928 25 0 0 28 830 310 254
## 1551 35 1 0 38 4370 315 374
## 1619 31 0 0 31 990 340 278
## 1780 25 2 0 25 900 325 253
## 2437 28 1 0 27 980 320 265
## 2452 28 0 0 26 930 345 245
## Tipo.parto Ospedale Sesso
## 928 Nat osp1 F
## 1551 Nat osp3 F
## 1619 Ces osp2 F
## 1780 Nat osp3 F
## 2437 Nat osp1 M
## 2452 Ces osp3 F
dati[dati$Cranio < 250 | dati$Cranio > 450, ]
## Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio
## 2175 37 8 0 28 930 355 235
## 2452 28 0 0 26 930 345 245
## Tipo.parto Ospedale Sesso
## 2175 Nat osp1 F
## 2452 Ces osp3 F
# Controllo le categorie
table(dati$Fumatrice)
## < table of extent 0 >
table(dati$N.gravidanze)
##
## 0 1 2 3 4 5 6 7 8 9 10 11 12
## 1096 818 340 150 48 21 11 1 8 2 3 1 1
table(dati$Tipo.parto)
##
## Ces Nat
## 728 1772
table(dati$Ospedale)
##
## osp1 osp2 osp3
## 816 849 835
table(dati$Sesso)
##
## F M
## 1256 1244
Riassumo il numero di valori sospetti per ogni variabile, così da capire quali dati richiedono una correzione prima delle analisi.
# Conto le osservazioni sospette
anomalie <- data.frame(
Variabile = c("Età madre", "Gestazione", "Peso",
"Lunghezza", "Cranio"),
Valori_sospetti = c(
sum(dati$Anni.madre < 12 | dati$Anni.madre > 55),
sum(dati$Gestazione < 22 | dati$Gestazione > 44),
sum(dati$Peso < 500 | dati$Peso > 6000),
sum(dati$Lunghezza < 350 | dati$Lunghezza > 600),
sum(dati$Cranio < 250 | dati$Cranio > 450)
)
)
print(anomalie, row.names = FALSE)
## Variabile Valori_sospetti
## Età madre 2
## Gestazione 0
## Peso 0
## Lunghezza 6
## Cranio 2
Controllo più nel dettaglio i valori sospetti per capire quali potrebbero essere errori e quali invece osservazioni reali.
# Individuo le righe con almeno un valore sospetto
sospetti <- which(
dati$Anni.madre < 12 | dati$Anni.madre > 55 |
dati$Gestazione < 22 | dati$Gestazione > 44 |
dati$Peso < 500 | dati$Peso > 6000 |
dati$Lunghezza < 350 | dati$Lunghezza > 600 |
dati$Cranio < 250 | dati$Cranio > 450
)
# Mostro le osservazioni e i loro numeri di riga
dettaglio <- data.frame(
Riga = sospetti,
dati[sospetti, ]
)
print(dettaglio, row.names = FALSE)
## Riga Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio
## 928 25 0 0 28 830 310 254
## 1152 1 1 0 41 3250 490 350
## 1380 0 0 0 39 3060 490 330
## 1551 35 1 0 38 4370 315 374
## 1619 31 0 0 31 990 340 278
## 1780 25 2 0 25 900 325 253
## 2175 37 8 0 28 930 355 235
## 2437 28 1 0 27 980 320 265
## 2452 28 0 0 26 930 345 245
## Tipo.parto Ospedale Sesso
## Nat osp1 F
## Nat osp2 F
## Nat osp3 M
## Nat osp3 F
## Ces osp2 F
## Nat osp3 F
## Nat osp1 F
## Nat osp1 M
## Ces osp3 F
Il controllo ha evidenziato due età materne non plausibili (0 e 1 anno), che vengono considerate mancanti. Le altre osservazioni sospette vengono mantenute perché potrebbero riferirsi a nascite premature.
Converto anche le misure di lunghezza e diametro craniale da millimetri a centimetri e preparo le variabili categoriche per le analisi successive.
# Creo una copia del dataset originale
dati_puliti <- dati
# Correggo le età materne non plausibili
dati_puliti$Anni.madre[dati_puliti$Anni.madre < 12] <- NA
# Converto le misure in centimetri
dati_puliti$Lunghezza <- dati_puliti$Lunghezza / 10
dati_puliti$Cranio <- dati_puliti$Cranio / 10
# Converto le variabili categoriche in fattori
# Converto la variabile in fattore
dati_puliti$Fumatrici <- factor(dati_puliti$Fumatrici,
levels = c(0, 1),
labels = c("No", "Si"))
dati_puliti$Tipo.parto <- factor(dati_puliti$Tipo.parto,
levels = c("Nat", "Ces"),
labels = c("Naturale", "Cesareo"))
dati_puliti$Ospedale <- factor(dati_puliti$Ospedale,
levels = c("osp1", "osp2", "osp3"))
dati_puliti$Sesso <- factor(dati_puliti$Sesso,
levels = c("F", "M"))
# Controllo il risultato
summary(dati_puliti)
## Anni.madre N.gravidanze Fumatrici Gestazione Peso
## Min. :13.00 Min. : 0.0000 No:2396 Min. :25.00 Min. : 830
## 1st Qu.:25.00 1st Qu.: 0.0000 Si: 104 1st Qu.:38.00 1st Qu.:2990
## Median :28.00 Median : 1.0000 Median :39.00 Median :3300
## Mean :28.19 Mean : 0.9812 Mean :38.98 Mean :3284
## 3rd Qu.:32.00 3rd Qu.: 1.0000 3rd Qu.:40.00 3rd Qu.:3620
## Max. :46.00 Max. :12.0000 Max. :43.00 Max. :4930
## NA's :2
## Lunghezza Cranio Tipo.parto Ospedale Sesso
## Min. :31.00 Min. :23.5 Naturale:1772 osp1:816 F:1256
## 1st Qu.:48.00 1st Qu.:33.0 Cesareo : 728 osp2:849 M:1244
## Median :50.00 Median :34.0 osp3:835
## Mean :49.47 Mean :34.0
## 3rd Qu.:51.00 3rd Qu.:35.0
## Max. :56.50 Max. :39.0
##
colSums(is.na(dati_puliti))
## Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza
## 2 0 0 0 0 0
## Cranio Tipo.parto Ospedale Sesso
## 0 0 0 0
Per capire meglio come sono distribuiti i dati, utilizzo istogrammi e boxplot. Questi grafici permettono di osservare i valori più frequenti e individuare eventuali valori estremi.
# Seleziono le variabili quantitative
variabili <- c("Anni.madre", "N.gravidanze", "Gestazione",
"Peso", "Lunghezza", "Cranio")
# Istogrammi
par(mfrow = c(2, 3), mar = c(4, 4, 3, 1))
for (v in variabili) {
hist(dati_puliti[[v]],
main = v,
xlab = v,
col = "lightblue",
border = "white")
}
# Boxplot
par(mfrow = c(2, 3), mar = c(4, 4, 3, 1))
for (v in variabili) {
boxplot(dati_puliti[[v]],
main = v,
col = "lightgreen")
}
# Ripristino la finestra grafica
par(mfrow = c(1, 1))
La maggior parte delle madri ha un’età compresa tra 25 e 32 anni e presenta poche gravidanze precedenti.
Le nascite si concentrano soprattutto tra la 38ª e la 40ª settimana di gestazione. Il peso dei neonati è generalmente vicino ai 3.300 g, mentre la lunghezza è intorno ai 50 cm e il diametro craniale ai 34 cm.
I boxplot evidenziano diversi valori estremi, soprattutto per peso, lunghezza, diametro craniale e settimane di gestazione. Questi valori potrebbero essere legati alle nascite premature e, non essendo necessariamente errori, sono stati mantenuti nelle analisi.
Controllo la frequenza delle diverse categorie per capire come sono distribuite le nascite nel dataset.
# Seleziono le variabili categoriche
categoriche <- c("Fumatrici", "Tipo.parto", "Ospedale", "Sesso")
# Grafici a barre
par(mfrow = c(2, 2), mar = c(4, 4, 3, 1))
for (v in categoriche) {
barplot(table(dati_puliti[[v]]),
main = v,
ylab = "Numero di nascite",
col = "lightblue")
}
par(mfrow = c(1, 1))
# Tabella delle frequenze e percentuali
for (v in categoriche) {
cat("\n", v, "\n")
print(table(dati_puliti[[v]]))
print(round(prop.table(table(dati_puliti[[v]])) * 100, 1))
}
##
## Fumatrici
##
## No Si
## 2396 104
##
## No Si
## 95.8 4.2
##
## Tipo.parto
##
## Naturale Cesareo
## 1772 728
##
## Naturale Cesareo
## 70.9 29.1
##
## Ospedale
##
## osp1 osp2 osp3
## 816 849 835
##
## osp1 osp2 osp3
## 32.6 34.0 33.4
##
## Sesso
##
## F M
## 1256 1244
##
## F M
## 50.2 49.8
La maggior parte delle madri non fuma (95,8%), mentre le fumatrici rappresentano il 4,2% del campione.
Il parto naturale è il più frequente (70,9%), mentre il cesareo riguarda il 29,1% delle nascite.
Le osservazioni sono distribuite in modo abbastanza uniforme tra i tre ospedali e anche tra i due sessi, con il 50,2% di femmine e il 49,8% di maschi.
Questa distribuzione permette di confrontare gruppi con numerosità simili per ospedale e sesso. Le madri fumatrici, invece, sono molto meno numerose.
Voglio verificare se la percentuale di parti cesarei cambia tra i tre ospedali.
Le ipotesi sono:
Utilizzo il test chi-quadrato di Pearson perché entrambe le variabili sono categoriche.
# Creo la tabella di contingenza
tabella_cesarei <- table(dati_puliti$Ospedale,
dati_puliti$Tipo.parto)
tabella_cesarei
##
## Naturale Cesareo
## osp1 574 242
## osp2 595 254
## osp3 603 232
# Calcolo le percentuali per ospedale
round(prop.table(tabella_cesarei, 1) * 100, 1)
##
## Naturale Cesareo
## osp1 70.3 29.7
## osp2 70.1 29.9
## osp3 72.2 27.8
# Test chi-quadrato
test_cesarei <- chisq.test(tabella_cesarei)
test_cesarei
##
## Pearson's Chi-squared test
##
## data: tabella_cesarei
## X-squared = 1.0972, df = 2, p-value = 0.5778
# Controllo le frequenze attese
test_cesarei$expected
##
## Naturale Cesareo
## osp1 578.3808 237.6192
## osp2 601.7712 247.2288
## osp3 591.8480 243.1520
Le percentuali di parti cesarei sono abbastanza simili nei tre ospedali: 29,7% nel primo, 29,9% nel secondo e 27,8% nel terzo.
Il test chi-quadrato restituisce un p-value di 0,578, superiore a 0,05. Non possiamo quindi affermare che esistano differenze statisticamente significative nel ricorso al cesareo tra gli ospedali.
Le differenze osservate sono piccole, ma questo non dimostra che i tre ospedali si comportino esattamente allo stesso modo.
Verifico se il peso e la lunghezza medi dei neonati sono diversi dai valori di riferimento italiani: 3.300 g e 50 cm.
Per il peso:
Per la lunghezza:
Utilizzo due test t a un campione, perché confronto le medie del campione con valori di riferimento e non conosco la deviazione standard della popolazione.
# Test sul peso medio
test_peso <- t.test(dati_puliti$Peso, mu = 3300)
test_peso
##
## One Sample t-test
##
## data: dati_puliti$Peso
## t = -1.516, df = 2499, p-value = 0.1296
## alternative hypothesis: true mean is not equal to 3300
## 95 percent confidence interval:
## 3263.490 3304.672
## sample estimates:
## mean of x
## 3284.081
# Test sulla lunghezza media
test_lunghezza <- t.test(dati_puliti$Lunghezza, mu = 50)
test_lunghezza
##
## One Sample t-test
##
## data: dati_puliti$Lunghezza
## t = -10.084, df = 2499, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 50
## 95 percent confidence interval:
## 49.36598 49.57242
## sample estimates:
## mean of x
## 49.4692
Il peso medio dei neonati è di 3.284 g, leggermente inferiore al riferimento italiano di 3.300 g. Il p-value è 0,130, quindi la differenza non è statisticamente significativa. L’intervallo di confidenza al 95% va da 3.263 a 3.305 g e comprende il valore di riferimento.
La lunghezza media è di 49,47 cm, circa 0,53 cm in meno rispetto ai 50 cm di riferimento. In questo caso il p-value è inferiore a 0,001 e l’intervallo di confidenza va da 49,37 a 49,57 cm.
Possiamo quindi dire che il peso medio è compatibile con il riferimento, mentre la lunghezza media risulta statisticamente inferiore. La differenza di lunghezza è comunque contenuta e non possiamo stabilire da questi dati se abbia un’importanza clinica.
Verifico se peso, lunghezza e diametro craniale sono diversi tra neonati maschi e femmine.
Per ciascuna misura considero:
Utilizzo il test t di Welch per campioni indipendenti, perché confronto due gruppi distinti senza assumere che abbiano la stessa varianza.
# Confronto il peso
t.test(Peso ~ Sesso, data = dati_puliti)
##
## Welch Two Sample t-test
##
## data: Peso by Sesso
## t = -12.106, df = 2490.7, p-value < 2.2e-16
## alternative hypothesis: true difference in means between group F and group M is not equal to 0
## 95 percent confidence interval:
## -287.1051 -207.0615
## sample estimates:
## mean in group F mean in group M
## 3161.132 3408.215
# Confronto la lunghezza
t.test(Lunghezza ~ Sesso, data = dati_puliti)
##
## Welch Two Sample t-test
##
## data: Lunghezza by Sesso
## t = -9.582, df = 2459.3, p-value < 2.2e-16
## alternative hypothesis: true difference in means between group F and group M is not equal to 0
## 95 percent confidence interval:
## -1.1929470 -0.7876273
## sample estimates:
## mean in group F mean in group M
## 48.97643 49.96672
# Confronto il diametro craniale
t.test(Cranio ~ Sesso, data = dati_puliti)
##
## Welch Two Sample t-test
##
## data: Cranio by Sesso
## t = -7.4102, df = 2491.4, p-value = 1.718e-13
## alternative hypothesis: true difference in means between group F and group M is not equal to 0
## 95 percent confidence interval:
## -0.6089912 -0.3541270
## sample estimates:
## mean in group F mean in group M
## 33.76330 34.24486
# Visualizzo le differenze
par(mfrow = c(1, 3), mar = c(4, 4, 3, 1))
boxplot(Peso ~ Sesso, data = dati_puliti,
main = "Peso", ylab = "Grammi",
col = "lightblue")
boxplot(Lunghezza ~ Sesso, data = dati_puliti,
main = "Lunghezza", ylab = "Centimetri",
col = "lightblue")
boxplot(Cranio ~ Sesso, data = dati_puliti,
main = "Diametro craniale", ylab = "Centimetri",
col = "lightblue")
par(mfrow = c(1, 1))
Dai boxplot si osserva che i neonati maschi tendono ad avere misure antropometriche maggiori rispetto alle femmine.
La lunghezza media è di 48,98 cm nelle femmine e 49,97 cm nei maschi, con una differenza di circa 0,99 cm. Il p-value è inferiore a 0,001, quindi la differenza è statisticamente significativa.
Anche il diametro craniale risulta maggiore nei maschi: 34,24 cm contro 33,76 cm nelle femmine, con una differenza di circa 0,48 cm. Anche in questo caso il p-value è inferiore a 0,001.
Questi risultati indicano differenze medie tra i due sessi, anche se le distribuzioni si sovrappongono ampiamente.
Anche il peso medio è maggiore nei maschi, con 3.408 g rispetto ai 3.161 g delle femmine. La differenza è di circa 247 g ed è statisticamente significativa (p-value < 0,001). L’intervallo di confidenza al 95% indica una differenza compresa tra circa 207 e 287 g.
Nel complesso, i tre test mostrano differenze significative tra maschi e femmine per peso, lunghezza e diametro craniale. Queste differenze riguardano le medie dei gruppi e non necessariamente ogni singolo neonato.
Prima di costruire il modello, controllo le correlazioni tra il peso alla nascita e le altre variabili quantitative. Utilizzo il coefficiente di Pearson e gli scatterplot per capire quali relazioni sono più evidenti.
# Seleziono le variabili quantitative
variabili_num <- dati_puliti[, c("Anni.madre", "N.gravidanze",
"Gestazione", "Peso",
"Lunghezza", "Cranio")]
# Matrice di correlazione
round(cor(variabili_num, use = "complete.obs"), 2)
## Anni.madre N.gravidanze Gestazione Peso Lunghezza Cranio
## Anni.madre 1.00 0.38 -0.13 -0.02 -0.06 0.02
## N.gravidanze 0.38 1.00 -0.10 0.00 -0.06 0.04
## Gestazione -0.13 -0.10 1.00 0.59 0.62 0.46
## Peso -0.02 0.00 0.59 1.00 0.80 0.70
## Lunghezza -0.06 -0.06 0.62 0.80 1.00 0.60
## Cranio 0.02 0.04 0.46 0.70 0.60 1.00
# Scatterplot del peso rispetto agli altri predittori
par(mfrow = c(2, 3), mar = c(4, 4, 3, 1))
for (v in c("Anni.madre", "N.gravidanze", "Gestazione",
"Lunghezza", "Cranio")) {
plot(dati_puliti[[v]], dati_puliti$Peso,
main = paste("Peso e", v),
xlab = v,
ylab = "Peso (g)",
pch = 20,
col = "steelblue")
}
par(mfrow = c(1, 1))
Il peso alla nascita presenta una correlazione positiva soprattutto con la lunghezza (r = 0,80), il diametro craniale (r = 0,70) e le settimane di gestazione (r = 0,59).
Questo significa che, in generale, i neonati più lunghi, con un diametro craniale maggiore e nati dopo più settimane di gestazione tendono a pesare di più.
L’età materna e il numero di gravidanze precedenti mostrano invece correlazioni molto deboli con il peso.
Gli scatterplot confermano queste relazioni. Si nota inoltre una correlazione tra lunghezza e gestazione (r = 0,62), che sarà utile considerare quando analizzeremo il modello multiplo.
Queste correlazioni indicano delle associazioni tra variabili, ma non dimostrano rapporti di causa-effetto.
Costruisco un primo modello di regressione lineare multipla utilizzando tutte le variabili disponibili come predittori del peso alla nascita.
L’obiettivo è capire quali variabili sono maggiormente associate al peso, tenendo conto contemporaneamente delle altre.
# Creo il modello completo
mod1 <- lm(Peso ~ Anni.madre + N.gravidanze + Fumatrici +
Gestazione + Lunghezza + Cranio +
Tipo.parto + Ospedale + Sesso,
data = dati_puliti)
# Visualizzo i risultati
summary(mod1)
##
## Call:
## lm(formula = Peso ~ Anni.madre + N.gravidanze + Fumatrici + Gestazione +
## Lunghezza + Cranio + Tipo.parto + Ospedale + Sesso, data = dati_puliti)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1123.26 -181.53 -14.45 161.05 2611.89
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6706.1625 141.1085 -47.525 < 2e-16 ***
## Anni.madre 0.8018 1.1467 0.699 0.4845
## N.gravidanze 11.3812 4.6686 2.438 0.0148 *
## FumatriciSi -30.2741 27.5492 -1.099 0.2719
## Gestazione 32.5773 3.8208 8.526 < 2e-16 ***
## Lunghezza 102.9218 3.0088 34.207 < 2e-16 ***
## Cranio 104.7221 4.2627 24.567 < 2e-16 ***
## Tipo.partoCesareo -29.6335 12.0905 -2.451 0.0143 *
## Ospedaleosp2 -11.0912 13.4471 -0.825 0.4096
## Ospedaleosp3 28.2495 13.5054 2.092 0.0366 *
## SessoM 77.5723 11.1865 6.934 5.18e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 274 on 2487 degrees of freedom
## (2 osservazioni eliminate a causa di valori mancanti)
## Multiple R-squared: 0.7289, Adjusted R-squared: 0.7278
## F-statistic: 668.7 on 10 and 2487 DF, p-value: < 2.2e-16
# Controllo il numero di osservazioni utilizzate
nobs(mod1)
## [1] 2498
# Calcolo AIC e BIC
AIC(mod1)
## [1] 35145.57
BIC(mod1)
## [1] 35215.45
Il modello completo spiega circa il 72,9% della variabilità del peso alla nascita (R² = 0,729), con un errore standard residuo di circa 274 g.
I coefficienti indicano come cambia mediamente il peso stimato al variare di una caratteristica, mantenendo costanti le altre.
| Variabile | Coefficiente | Interpretazione |
|---|---|---|
| Età materna | +0,80 g | Associazione molto debole, non significativa (p = 0,485). |
| Gravidanze precedenti | +11,38 g | Circa 11 g in più per ogni gravidanza precedente (p = 0,015). |
| Fumo materno | -30,27 g | Le fumatrici hanno un peso stimato inferiore di circa 30 g, ma la differenza non è significativa (p = 0,272). |
| Gestazione | +32,58 g | Circa 33 g in più per ogni settimana aggiuntiva (p < 0,001). |
| Lunghezza | +102,92 g | Circa 103 g in più per ogni centimetro (p < 0,001). |
| Diametro craniale | +104,72 g | Circa 105 g in più per ogni centimetro (p < 0,001). |
| Parto cesareo | -29,63 g | Circa 30 g in meno rispetto al parto naturale (p = 0,014). |
| Ospedale 2 | -11,09 g | Differenza non significativa rispetto all’ospedale 1 (p = 0,410). |
| Ospedale 3 | +28,25 g | Circa 28 g in più rispetto all’ospedale 1 (p = 0,037). |
| Sesso maschile | +77,57 g | Circa 78 g in più rispetto alle femmine (p < 0,001). |
Le associazioni più evidenti riguardano lunghezza, diametro craniale e gestazione. L’età materna e il fumo non risultano significativi nel modello completo.
Questi risultati mostrano delle associazioni statistiche e non dimostrano necessariamente rapporti di causa-effetto.
Provo a semplificare il modello eliminando inizialmente l’età materna, che non risulta significativa. Confronto poi i due modelli per verificare se la sua esclusione peggiora l’adattamento.
# Creo il modello senza età materna
mod2 <- update(mod1, ~ . - Anni.madre)
# Confronto i risultati
summary(mod2)
##
## Call:
## lm(formula = Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza +
## Cranio + Tipo.parto + Ospedale + Sesso, data = dati_puliti)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1113.93 -180.11 -16.36 160.58 2616.96
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6678.571 135.543 -49.273 < 2e-16 ***
## N.gravidanze 12.608 4.338 2.906 0.00369 **
## FumatriciSi -30.309 27.536 -1.101 0.27113
## Gestazione 32.250 3.797 8.494 < 2e-16 ***
## Lunghezza 102.944 3.007 34.239 < 2e-16 ***
## Cranio 104.876 4.255 24.651 < 2e-16 ***
## Tipo.partoCesareo -29.535 12.083 -2.444 0.01458 *
## Ospedaleosp2 -11.082 13.436 -0.825 0.40957
## Ospedaleosp3 28.366 13.490 2.103 0.03559 *
## SessoM 77.621 11.176 6.945 4.81e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 273.9 on 2490 degrees of freedom
## Multiple R-squared: 0.7288, Adjusted R-squared: 0.7278
## F-statistic: 743.6 on 9 and 2490 DF, p-value: < 2.2e-16
# Confronto i modelli sugli stessi dati
dati_confronto <- dati_puliti[complete.cases(
dati_puliti[, c("Anni.madre", "N.gravidanze", "Fumatrici",
"Gestazione", "Lunghezza", "Cranio",
"Tipo.parto", "Ospedale", "Sesso")]), ]
mod2_confronto <- lm(formula(mod2), data = dati_confronto)
anova(mod2_confronto, mod1)
## Analysis of Variance Table
##
## Model 1: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio +
## Tipo.parto + Ospedale + Sesso
## Model 2: Peso ~ Anni.madre + N.gravidanze + Fumatrici + Gestazione + Lunghezza +
## Cranio + Tipo.parto + Ospedale + Sesso
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 2488 186779904
## 2 2487 186743194 1 36710 0.4889 0.4845
# Confronto R² aggiustato, AIC e BIC
AIC(mod1, mod2_confronto)
## df AIC
## mod1 12 35145.57
## mod2_confronto 11 35144.06
BIC(mod1, mod2_confronto)
## df BIC
## mod1 12 35215.45
## mod2_confronto 11 35208.12
Eliminando l’età materna, il modello mantiene praticamente lo stesso R² aggiustato (0,728).
Il confronto ANOVA non mostra un peggioramento significativo (p = 0,485). Anche AIC e BIC diminuiscono leggermente, indicando che il modello più semplice è preferibile.
Decido quindi di escludere l’età materna dai predittori.
Verifico se mantenere la variabile ospedale migliora il modello. Per farlo confronto il modello precedente con una versione senza questo predittore.
# Uso le stesse osservazioni per il confronto
mod2_base <- mod2_confronto
# Creo il modello senza ospedale
mod3 <- update(mod2_base, ~ . - Ospedale)
# Confronto i modelli
summary(mod3)
##
## Call:
## lm(formula = Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza +
## Cranio + Tipo.parto + Sesso, data = dati_confronto)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1129.88 -181.36 -16.24 160.63 2634.62
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6678.385 135.662 -49.228 < 2e-16 ***
## N.gravidanze 12.993 4.344 2.991 0.00281 **
## FumatriciSi -31.882 27.580 -1.156 0.24780
## Gestazione 32.597 3.804 8.569 < 2e-16 ***
## Lunghezza 102.684 3.011 34.098 < 2e-16 ***
## Cranio 105.015 4.262 24.637 < 2e-16 ***
## Tipo.partoCesareo -30.424 12.104 -2.514 0.01201 *
## SessoM 78.103 11.200 6.974 3.94e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 274.4 on 2490 degrees of freedom
## Multiple R-squared: 0.7278, Adjusted R-squared: 0.7271
## F-statistic: 951.3 on 7 and 2490 DF, p-value: < 2.2e-16
anova(mod3, mod2_base)
## Analysis of Variance Table
##
## Model 1: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio +
## Tipo.parto + Sesso
## Model 2: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio +
## Tipo.parto + Ospedale + Sesso
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 2490 187473818
## 2 2488 186779904 2 693914 4.6216 0.009921 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Confronto AIC e BIC
AIC(mod2_base, mod3)
## df AIC
## mod2_base 11 35144.06
## mod3 9 35149.33
BIC(mod2_base, mod3)
## df BIC
## mod2_base 11 35208.12
## mod3 9 35201.73
Eliminando la variabile Ospedale, l’R² aggiustato diminuisce leggermente da 0,7278 a 0,7271.
Il test ANOVA indica un peggioramento statisticamente significativo (p = 0,010). L’AIC favorisce il modello con Ospedale, mentre il BIC preferisce quello più semplice.
Dato che l’azienda è interessata anche alle differenze tra strutture, decido per il momento di mantenere questa variabile.
Dallo scatterplot tra gestazione e peso si nota che la relazione potrebbe non essere perfettamente lineare.
Provo quindi ad aggiungere un termine quadratico per verificare se migliora il modello.
# Parto dal modello senza età materna
mod_base <- mod2_base
# Aggiungo il termine quadratico della gestazione
mod_quadratico <- update(mod_base, ~ . + I(Gestazione^2))
# Controllo il nuovo modello
summary(mod_quadratico)
##
## Call:
## lm(formula = Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza +
## Cranio + Tipo.parto + Ospedale + Sesso + I(Gestazione^2),
## data = dati_confronto)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1143.27 -181.03 -12.92 162.57 2637.95
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -4792.2523 897.3309 -5.341 1.01e-07 ***
## N.gravidanze 12.6685 4.3371 2.921 0.00352 **
## FumatriciSi -29.2938 27.5312 -1.064 0.28742
## Gestazione -73.0509 49.6761 -1.471 0.14154
## Lunghezza 103.8794 3.0403 34.168 < 2e-16 ***
## Cranio 105.7828 4.2751 24.744 < 2e-16 ***
## Tipo.partoCesareo -29.2306 12.0824 -2.419 0.01562 *
## Ospedaleosp2 -10.1949 13.4394 -0.759 0.44817
## Ospedaleosp3 28.1888 13.4900 2.090 0.03675 *
## SessoM 75.5911 11.2186 6.738 1.99e-11 ***
## I(Gestazione^2) 1.4064 0.6612 2.127 0.03352 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 273.8 on 2487 degrees of freedom
## Multiple R-squared: 0.7293, Adjusted R-squared: 0.7283
## F-statistic: 670.2 on 10 and 2487 DF, p-value: < 2.2e-16
# Confronto i due modelli
anova(mod_base, mod_quadratico)
## Analysis of Variance Table
##
## Model 1: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio +
## Tipo.parto + Ospedale + Sesso
## Model 2: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio +
## Tipo.parto + Ospedale + Sesso + I(Gestazione^2)
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 2488 186779904
## 2 2487 186440757 1 339147 4.524 0.03352 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Confronto AIC e BIC
AIC(mod_base, mod_quadratico)
## df AIC
## mod_base 11 35144.06
## mod_quadratico 12 35141.52
BIC(mod_base, mod_quadratico)
## df BIC
## mod_base 11 35208.12
## mod_quadratico 12 35211.40
Aggiungendo il termine quadratico della gestazione, l’R² aggiustato aumenta leggermente da 0,7278 a 0,7283.
Il miglioramento risulta statisticamente significativo (p = 0,034), ma è molto piccolo. L’AIC favorisce il modello quadratico, mentre il BIC preferisce quello lineare.
Per semplicità, decido di mantenere il modello lineare, che offre risultati molto simili ed è più facile da interpretare.
Verifico se la relazione tra settimane di gestazione e peso alla nascita cambia tra madri fumatrici e non fumatrici.
Aggiungo quindi un termine di interazione e confronto il nuovo modello con quello precedente.
# Aggiungo l'interazione tra gestazione e fumo
mod_interazione <- update(mod_base, ~ . + Gestazione:Fumatrici)
# Controllo i risultati
summary(mod_interazione)
##
## Call:
## lm(formula = Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza +
## Cranio + Tipo.parto + Ospedale + Sesso + Fumatrici:Gestazione,
## data = dati_confronto)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1113.3 -180.9 -16.6 161.1 2616.2
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6697.460 136.563 -49.043 < 2e-16 ***
## N.gravidanze 12.634 4.340 2.911 0.00363 **
## FumatriciSi 839.377 755.923 1.110 0.26693
## Gestazione 32.885 3.833 8.579 < 2e-16 ***
## Lunghezza 102.858 3.009 34.187 < 2e-16 ***
## Cranio 104.817 4.257 24.624 < 2e-16 ***
## Tipo.partoCesareo -29.865 12.090 -2.470 0.01357 *
## Ospedaleosp2 -10.619 13.446 -0.790 0.42978
## Ospedaleosp3 28.858 13.501 2.137 0.03266 *
## SessoM 78.261 11.197 6.989 3.53e-12 ***
## FumatriciSi:Gestazione -22.156 19.242 -1.151 0.24967
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 274 on 2487 degrees of freedom
## Multiple R-squared: 0.729, Adjusted R-squared: 0.7279
## F-statistic: 669 on 10 and 2487 DF, p-value: < 2.2e-16
# Confronto i modelli
anova(mod_base, mod_interazione)
## Analysis of Variance Table
##
## Model 1: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio +
## Tipo.parto + Ospedale + Sesso
## Model 2: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio +
## Tipo.parto + Ospedale + Sesso + Fumatrici:Gestazione
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 2488 186779904
## 2 2487 186680389 1 99515 1.3258 0.2497
# Confronto AIC e BIC
AIC(mod_base, mod_interazione)
## df AIC
## mod_base 11 35144.06
## mod_interazione 12 35144.73
BIC(mod_base, mod_interazione)
## df BIC
## mod_base 11 35208.12
## mod_interazione 12 35214.61
L’interazione tra fumo materno e settimane di gestazione non risulta statisticamente significativa (p = 0,250).
L’R² aggiustato rimane praticamente invariato, mentre AIC e BIC aumentano leggermente.
Decido quindi di non inserire questa interazione nel modello, perché non porta un miglioramento utile.
Dopo i confronti effettuati, scelgo un modello più semplice rispetto a quello iniziale, eliminando l’età materna e senza aggiungere termini quadratici o interazioni.
Mantengo le altre variabili e controllo la presenza di multicollinearità.
# Seleziono il modello
mod_finale <- mod2_base
# Riepilogo del modello
summary(mod_finale)
##
## Call:
## lm(formula = formula(mod2), data = dati_confronto)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1113.82 -180.30 -16.22 160.66 2616.32
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6678.954 135.623 -49.247 < 2e-16 ***
## N.gravidanze 12.583 4.340 2.899 0.00377 **
## FumatriciSi -30.427 27.545 -1.105 0.26944
## Gestazione 32.300 3.800 8.501 < 2e-16 ***
## Lunghezza 102.916 3.008 34.209 < 2e-16 ***
## Cranio 104.874 4.257 24.638 < 2e-16 ***
## Tipo.partoCesareo -29.665 12.089 -2.454 0.01420 *
## Ospedaleosp2 -10.951 13.444 -0.815 0.41541
## Ospedaleosp3 28.517 13.499 2.113 0.03474 *
## SessoM 77.645 11.185 6.942 4.91e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 274 on 2488 degrees of freedom
## Multiple R-squared: 0.7288, Adjusted R-squared: 0.7279
## F-statistic: 743.1 on 9 and 2488 DF, p-value: < 2.2e-16
# Controllo la multicollinearità
car::vif(mod_finale)
## GVIF Df GVIF^(1/(2*Df))
## N.gravidanze 1.027985 1 1.013896
## Fumatrici 1.007363 1 1.003675
## Gestazione 1.677351 1 1.295126
## Lunghezza 2.086862 1 1.444597
## Cranio 1.626789 1 1.275456
## Tipo.parto 1.004213 1 1.002104
## Ospedale 1.003460 2 1.000864
## Sesso 1.040653 1 1.020124
Il modello selezionato mantiene un R² aggiustato di 0,728 e un errore standard residuo di circa 274 g.
Il controllo della multicollinearità non mostra problemi particolari: tutti i valori risultano contenuti.
I predittori possono quindi essere mantenuti nel modello, che passerà ora ai controlli diagnostici.
Controllo i residui del modello per verificare se presentano andamenti particolari, se la loro variabilità è costante e se ci sono osservazioni potenzialmente influenti.
# Visualizzo i quattro grafici diagnostici
par(mfrow = c(2, 2))
plot(mod_finale)
par(mfrow = c(1, 1))
Dai grafici si notano alcune anomalie, soprattutto nella distribuzione dei residui. Utilizzo alcuni test statistici per controllare meglio il modello.
# Test di Breusch-Pagan per la varianza costante
lmtest::bptest(mod_finale)
##
## studentized Breusch-Pagan test
##
## data: mod_finale
## BP = 91.153, df = 9, p-value = 9.554e-16
# Test di Durbin-Watson per l'autocorrelazione
lmtest::dwtest(mod_finale)
##
## Durbin-Watson test
##
## data: mod_finale
## DW = 1.9529, p-value = 0.1197
## alternative hypothesis: true autocorrelation is greater than 0
# Test di Shapiro-Wilk per la normalità
shapiro.test(residuals(mod_finale))
##
## Shapiro-Wilk normality test
##
## data: residuals(mod_finale)
## W = 0.97415, p-value < 2.2e-16
# Grafico della distribuzione dei residui
plot(density(residuals(mod_finale)),
main = "Distribuzione dei residui",
xlab = "Residui (g)",
col = "blue")
Il test di Breusch-Pagan è significativo (p < 0,001), quindi la variabilità dei residui non sembra costante.
Anche il test di Shapiro-Wilk è significativo (p < 0,001), indicando che i residui non seguono perfettamente una distribuzione normale. Il grafico mostra infatti una coda destra più lunga.
Il test di Durbin-Watson non evidenzia autocorrelazione significativa (p = 0,120), anche se il risultato dipende dall’ordine dei dati.
Il modello rimane utile, ma questi problemi rendono necessario interpretare con cautela i risultati statistici e le previsioni.
Controllo se alcune osservazioni hanno valori particolarmente diversi dalle altre e potrebbero influenzare le stime del modello.
Utilizzo i residui studentizzati, i valori di leverage e la distanza di Cook.
# Calcolo gli indicatori
lev <- hatvalues(mod_finale)
res_student <- rstudent(mod_finale)
cook <- cooks.distance(mod_finale)
# Soglie indicative
n <- nobs(mod_finale)
p <- length(coef(mod_finale))
soglia_lev <- 2 * p / n
soglia_cook <- 4 / n
# Grafici
par(mfrow = c(1, 3))
plot(lev, main = "Leverage",
ylab = "Leverage", pch = 20)
abline(h = soglia_lev, col = "red")
plot(res_student, main = "Residui studentizzati",
ylab = "Residui", pch = 20)
abline(h = c(-3, 3), col = "red")
plot(cook, main = "Distanza di Cook",
ylab = "Cook", pch = 20)
abline(h = soglia_cook, col = "red")
par(mfrow = c(1, 1))
# Numero di osservazioni oltre le soglie
data.frame(
Indicatore = c("Leverage", "Residui", "Cook"),
Osservazioni = c(
sum(lev > soglia_lev),
sum(abs(res_student) > 3),
sum(cook > soglia_cook)
)
)
## Indicatore Osservazioni
## 1 Leverage 184
## 2 Residui 22
## 3 Cook 128
# Mostro le 5 osservazioni con Cook maggiore
influenti <- order(cook, decreasing = TRUE)[1:5]
data.frame(
Riga_originale = as.integer(rownames(model.frame(mod_finale)))[influenti],
Cook = round(cook[influenti], 4),
Leverage = round(lev[influenti], 4),
Residuo = round(res_student[influenti], 2)
)
## Riga_originale Cook Leverage Residuo
## 1551 1551 0.5000 0.0495 9.99
## 310 310 0.0445 0.0297 -3.82
## 1920 1920 0.0260 0.0159 4.02
## 155 155 0.0205 0.0081 5.04
## 1780 1780 0.0193 0.0265 2.67
Il controllo individua 184 osservazioni con leverage elevato, 22 con residui studentizzati oltre ±3 e 128 sopra la soglia indicativa della distanza di Cook.
L’osservazione 1551 è quella più influente, con una distanza di Cook di 0,500 e un residuo studentizzato di circa 10.
Questi valori non indicano necessariamente errori. Prima di escludere eventuali osservazioni, verifico quanto influenzano i risultati del modello.
Per capire quanto l’osservazione 1551 influisce sul modello, provo a stimarlo nuovamente senza questo caso e confronto i coefficienti.
L’esclusione viene utilizzata soltanto come controllo, senza modificare il dataset originale.
# Controllo l'osservazione più influente
dati_puliti[1551, ]
## Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio
## 1551 35 1 No 38 4370 31.5 37.4
## Tipo.parto Ospedale Sesso
## 1551 Naturale osp3 F
# Creo un modello senza l'osservazione 1551
mod_senza_1551 <- update(
mod_finale,
subset = rownames(dati_confronto) != "1551"
)
# Confronto i coefficienti
confronto_coefficienti <- data.frame(
Variabile = names(coef(mod_finale)),
Originale = round(coef(mod_finale), 2),
Senza_1551 = round(coef(mod_senza_1551), 2)
)
confronto_coefficienti$Differenza <- round(
confronto_coefficienti$Senza_1551 -
confronto_coefficienti$Originale, 2
)
print(confronto_coefficienti, row.names = FALSE)
## Variabile Originale Senza_1551 Differenza
## (Intercept) -6678.95 -6680.23 -1.28
## N.gravidanze 12.58 13.26 0.68
## FumatriciSi -30.43 -27.45 2.98
## Gestazione 32.30 29.57 -2.73
## Lunghezza 102.92 109.31 6.39
## Cranio 104.87 98.72 -6.15
## Tipo.partoCesareo -29.67 -29.54 0.13
## Ospedaleosp2 -10.95 -11.63 -0.68
## Ospedaleosp3 28.52 25.34 -3.18
## SessoM 77.65 77.81 0.16
# Confronto l'adattamento
data.frame(
Modello = c("Originale", "Senza osservazione 1551"),
R2_aggiustato = c(
summary(mod_finale)$adj.r.squared,
summary(mod_senza_1551)$adj.r.squared
),
Errore_residuo = c(
sigma(mod_finale),
sigma(mod_senza_1551)
)
)
## Modello R2_aggiustato Errore_residuo
## 1 Originale 0.7278667 273.9933
## 2 Senza osservazione 1551 0.7379105 268.7130
L’osservazione 1551 presenta un peso di 4.370 g e una lunghezza di 31,5 cm, una combinazione piuttosto insolita che potrebbe indicare un errore nei dati.
Escludendo temporaneamente questa osservazione, l’R² aggiustato passa da 0,7279 a 0,7379 e l’errore residuo diminuisce da 273,99 a 268,71 g.
Anche i coefficienti cambiano molto poco. Il modello sembra quindi abbastanza stabile rispetto a questa singola osservazione.
Per prudenza mantengo il caso nel dataset, segnalando comunque la possibile anomalia.
Utilizzo il modello selezionato per stimare il peso di una neonata alla 39ª settimana di gestazione, con madre alla terza gravidanza.
Per le informazioni non specificate utilizzo valori medi del campione e categorie di riferimento. La previsione è quindi un esempio e non una stima clinica personalizzata.
# Creo il caso da prevedere
nuovo_caso <- data.frame(
N.gravidanze = 2,
Fumatrici = factor("No", levels = levels(dati_puliti$Fumatrici)),
Gestazione = 39,
Lunghezza = mean(dati_puliti$Lunghezza),
Cranio = mean(dati_puliti$Cranio),
Tipo.parto = factor("Naturale", levels = levels(dati_puliti$Tipo.parto)),
Ospedale = factor("osp1", levels = levels(dati_puliti$Ospedale)),
Sesso = factor("F", levels = levels(dati_puliti$Sesso))
)
# Mostro le caratteristiche utilizzate
nuovo_caso
## N.gravidanze Fumatrici Gestazione Lunghezza Cranio Tipo.parto Ospedale
## 1 2 No 39 49.4692 34.00292 Naturale osp1
## Sesso
## 1 F
# Previsione con intervallo al 95%
previsione <- predict(mod_finale,
newdata = nuovo_caso,
interval = "prediction",
level = 0.95)
round(previsione, 1)
## fit lwr upr
## 1 3263.1 2725.2 3800.9
Per il caso considerato, il modello prevede un peso alla nascita di circa 3.263 g.
L’intervallo di previsione al 95% va da circa 2.725 a 3.801 g. Questo intervallo indica che il peso effettivo della neonata potrebbe essere anche abbastanza diverso dalla stima centrale.
Il risultato è stato ottenuto assumendo che la madre non fumi, che il parto sia naturale e che avvenga nell’ospedale 1. Per lunghezza e diametro craniale sono state utilizzate le medie del campione.
La previsione è quindi indicativa e deve essere interpretata con cautela, anche considerando i problemi emersi nella diagnostica del modello.
Un limite importante riguarda le misure utilizzate per la previsione. Anche se lunghezza e diametro craniale possono essere stimati durante la gravidanza tramite ecografia, non sappiamo se i valori presenti nel dataset siano stati rilevati prima o dopo il parto.
Anche il tipo di parto potrebbe non essere noto in anticipo. Per questo motivo, il risultato deve essere considerato una simulazione indicativa e non una previsione clinica già utilizzabile durante la gravidanza.
Per rendere più chiari i risultati del modello, rappresento il peso previsto in base alle settimane di gestazione, distinguendo le madri fumatrici dalle non fumatrici.
Per le altre variabili utilizzo valori medi e categorie di riferimento.
# Creo i dati per le previsioni
nuovi_dati <- expand.grid(
N.gravidanze = 2,
Fumatrici = levels(dati_puliti$Fumatrici),
Gestazione = 25:43,
Lunghezza = mean(dati_puliti$Lunghezza),
Cranio = mean(dati_puliti$Cranio),
Tipo.parto = "Naturale",
Ospedale = "osp1",
Sesso = "F"
)
# Imposto le categorie
nuovi_dati$Fumatrici <- factor(nuovi_dati$Fumatrici,
levels = levels(dati_puliti$Fumatrici))
nuovi_dati$Tipo.parto <- factor(nuovi_dati$Tipo.parto,
levels = levels(dati_puliti$Tipo.parto))
nuovi_dati$Ospedale <- factor(nuovi_dati$Ospedale,
levels = levels(dati_puliti$Ospedale))
nuovi_dati$Sesso <- factor(nuovi_dati$Sesso,
levels = levels(dati_puliti$Sesso))
# Calcolo il peso previsto
nuovi_dati$Peso_previsto <- predict(mod_finale,
newdata = nuovi_dati)
# Grafico
library(ggplot2)
ggplot(nuovi_dati,
aes(x = Gestazione, y = Peso_previsto,
color = Fumatrici)) +
geom_line(linewidth = 1.2) +
labs(
title = "Peso previsto e settimane di gestazione",
x = "Settimane di gestazione",
y = "Peso previsto (g)",
color = "Madre fumatrice"
) +
theme_minimal()
Il grafico mostra che il peso previsto aumenta di circa 32 g per ogni settimana aggiuntiva di gestazione, mantenendo costanti le altre caratteristiche.
Le madri fumatrici presentano un peso stimato inferiore di circa 30 g rispetto alle non fumatrici. Questa differenza, però, non è statisticamente significativa (p = 0,269).
Le due linee sono parallele perché il modello non prevede un’interazione tra fumo e gestazione.
Le previsioni sono indicative e vanno interpretate con cautela, soprattutto per le gestazioni molto premature.
Rappresento il peso previsto in relazione alla lunghezza e al diametro craniale, che risultano tra le variabili maggiormente associate al peso alla nascita.
# Creo i dati per i grafici
dati_grafici <- data.frame(
N.gravidanze = 2,
Fumatrici = factor("No", levels = levels(dati_puliti$Fumatrici)),
Gestazione = 39,
Lunghezza = seq(45, 55, length.out = 100),
Cranio = mean(dati_puliti$Cranio),
Tipo.parto = factor("Naturale", levels = levels(dati_puliti$Tipo.parto)),
Ospedale = factor("osp1", levels = levels(dati_puliti$Ospedale)),
Sesso = factor("F", levels = levels(dati_puliti$Sesso))
)
# Previsione in base alla lunghezza
dati_grafici$Peso_previsto <- predict(mod_finale,
newdata = dati_grafici)
grafico_lunghezza <- ggplot(dati_grafici,
aes(x = Lunghezza, y = Peso_previsto)) +
geom_line(color = "steelblue", linewidth = 1.2) +
labs(title = "Peso previsto e lunghezza",
x = "Lunghezza (cm)",
y = "Peso previsto (g)") +
theme_minimal()
# Modifico i dati per il diametro craniale
dati_grafici$Lunghezza <- mean(dati_puliti$Lunghezza)
dati_grafici$Cranio <- seq(30, 38, length.out = 100)
dati_grafici$Peso_previsto <- predict(mod_finale,
newdata = dati_grafici)
grafico_cranio <- ggplot(dati_grafici,
aes(x = Cranio, y = Peso_previsto)) +
geom_line(color = "darkgreen", linewidth = 1.2) +
labs(title = "Peso previsto e diametro craniale",
x = "Diametro craniale (cm)",
y = "Peso previsto (g)") +
theme_minimal()
# Mostro i grafici
print(grafico_lunghezza)
print(grafico_cranio)
I grafici mostrano una relazione positiva tra il peso previsto e le misure antropometriche.
Secondo il modello, a parità delle altre caratteristiche, ogni centimetro aggiuntivo di lunghezza è associato a circa 103 g in più, mentre ogni centimetro aggiuntivo di diametro craniale è associato a circa 105 g in più.
Entrambe le relazioni risultano statisticamente significative (p < 0,001).
Questi risultati confermano che lunghezza e diametro craniale sono importanti per stimare il peso alla nascita, anche se da soli non permettono una previsione precisa.
L’analisi delle 2.500 nascite ha permesso di studiare le principali caratteristiche dei neonati e di costruire un modello per stimare il peso alla nascita.
I test statistici non hanno evidenziato differenze significative nella frequenza dei parti cesarei tra i tre ospedali.
Il peso medio del campione è risultato compatibile con il riferimento italiano di 3.300 g, mentre la lunghezza media è leggermente inferiore ai 50 cm di riferimento. Sono emerse anche differenze significative tra maschi e femmine per peso, lunghezza e diametro craniale.
Il modello finale spiega circa il 73% della variabilità del peso. Le variabili maggiormente associate al peso sono la lunghezza, il diametro craniale e le settimane di gestazione.
Per il caso richiesto, il peso previsto è di circa 3.263 g, con un intervallo di previsione al 95% compreso tra 2.725 e 3.801 g.
Il modello presenta però alcuni limiti. I residui non rispettano completamente le ipotesi di normalità e varianza costante, quindi i risultati vanno interpretati con cautela. Inoltre, alcune osservazioni sono potenzialmente anomale.
Un altro limite riguarda la disponibilità delle informazioni: per utilizzare il modello durante la gravidanza è necessario disporre di misure prenatali affidabili. Non tutte le informazioni utilizzate potrebbero essere disponibili prima del parto.
Nel complesso, il modello può essere utile per comprendere le relazioni tra le variabili e fornire stime indicative, ma non dovrebbe essere utilizzato da solo per prendere decisioni cliniche.