Obiettivo: Creare un modello statistico in grado di prevedere con precisione il peso dei neonati alla nascita, basandosi su variabili cliniche raccolte da tre ospedali. Il progetto mira a migliorare la gestione delle gravidanze ad alto rischio, ottimizzare le risorse ospedaliere e garantire migliori risultati per la salute neonatale.
Il progetto si inserisce all’interno di un contesto di crescente attenzione verso la prevenzione delle complicazioni neonatali. La possibilità di prevedere il peso alla nascita dei neonati rappresenta un’opportunità fondamentale per migliorare la pianificazione clinica e ridurre i rischi associati a nascite problematiche, come parti prematuri o neonati con basso peso. Di seguito, i principali benefici che questo progetto porterà all’azienda e al settore sanitario:
1.Miglioramento delle previsioni cliniche:
2.Ottimizzazione delle risorse ospedaliere:
3.Prevenzione e identificazione dei fattori di rischio:
4.Valutazione delle pratiche ospedaliere:
5.Supporto alla pianificazione strategica:
library(ggplot2)
library(moments)
library(corrplot)
library(car)
library(MASS)
library(stats)
library(dplyr)
library(lmtest)
library(knitr)
d <- read.csv("neonati.csv",
stringsAsFactors = FALSE,
fileEncoding = "UTF-8")
Controllo che il dataset sia stato caricato correttamente
head(d)
## Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio Tipo.parto
## 1 26 0 0 42 3380 490 325 Nat
## 2 21 2 0 39 3150 490 345 Nat
## 3 34 3 0 38 3640 500 375 Nat
## 4 28 1 0 41 3690 515 365 Nat
## 5 20 0 0 38 3700 480 335 Nat
## 6 32 0 0 40 3200 495 340 Nat
## Ospedale Sesso
## 1 osp3 M
## 2 osp1 F
## 3 osp2 M
## 4 osp2 M
## 5 osp3 F
## 6 osp2 F
Verifico che il dataset non presenti valori mancanti
data_na <- sum(is.na(d))
Il dataseta presenta 0 valori mancanti
Converto i dati in fattori e variabili numeriche a seconda che si tratti di variabili qualitative o quantitative
to_factor <- function(x) if(!is.null(x)) d[[x]] <<- factor(d[[x]])
cols <- c("Tipo.parto", "Ospedale", "Sesso")
d[cols] <- lapply(d[cols], factor)
d$Fumatrici <- factor(ifelse(d$Fumatrici == 1, "si", "no"))
cols <- c("Anni.madre", "N.gravidanze", "Gestazione", "Peso", "Lunghezza", "Cranio")
d[cols] <- lapply(d[cols], as.numeric)
Procediamo con un’analisi descrittiva delle variabili quantitative:
desc <- data.frame(
media = sapply(d[cols], mean, na.rm = TRUE),
median = sapply(d[cols], median, na.rm = TRUE),
min = sapply(d[cols], min, na.rm = TRUE),
max = sapply(d[cols], max, na.rm = TRUE),
qtl.25 = sapply(d[cols], quantile, probs=0.25,na.rm = TRUE),
qtl.75 = sapply(d[cols], quantile, probs=0.75,na.rm = TRUE),
sd = sapply(d[cols], sd, na.rm = TRUE),
skewness = sapply(d[cols], skewness, na.rm = TRUE),
kurtosi = sapply(d[cols], function(x) kurtosis(x, na.rm=TRUE)-3)
)
kable(desc)
| media | median | min | max | qtl.25 | qtl.75 | sd | skewness | kurtosi | |
|---|---|---|---|---|---|---|---|---|---|
| Anni.madre | 28.1640 | 28 | 0 | 46 | 25 | 32 | 5.273578 | 0.0428115 | 0.3804165 |
| N.gravidanze | 0.9812 | 1 | 0 | 12 | 0 | 1 | 1.280587 | 2.5142541 | 10.9894064 |
| Gestazione | 38.9804 | 39 | 25 | 43 | 38 | 40 | 1.868639 | -2.0653133 | 8.2581496 |
| Peso | 3284.0808 | 3300 | 830 | 4930 | 2990 | 3620 | 525.038744 | -0.6470308 | 2.0315318 |
| Lunghezza | 494.6920 | 500 | 310 | 565 | 480 | 510 | 26.318644 | -1.5146991 | 6.4871739 |
| Cranio | 340.0292 | 340 | 235 | 390 | 330 | 350 | 16.425330 | -0.7850527 | 2.9462063 |
Il valore minimo della variabile Anni.madre suggerisce che all’interno del dataset potrebbero esserci dei valori anomali o inseriti in maniera errata. Si procede quindi con l’identificazione e gestione degli outliers.
Implementiamo una funzione che identifica i valori oltre 1.5×IQR dal 1° e 3° quartile
find_outliers <- function(x) {
Q1 <- quantile(x, 0.25, na.rm = TRUE)
Q3 <- quantile(x, 0.75, na.rm = TRUE)
IQR <- Q3 - Q1
lower <- Q1 - 1.5 * IQR
upper <- Q3 + 1.5 * IQR
which(x < lower | x > upper)
}
cols <- c("Anni.madre", "N.gravidanze", "Gestazione", "Peso", "Lunghezza", "Cranio")
outlier_indices <- lapply(d[cols], find_outliers)
names(outlier_indices) <- cols
outliers_all <- unique(unlist(outlier_indices))
head(d[outliers_all, ]) # Visualizzo degli esempi delle righe che contengono almeno un outlier
## Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio
## 138 13 0 no 38 2760 470 325
## 205 45 2 no 38 3850 505 384
## 230 43 1 no 35 2050 455 305
## 260 44 1 no 40 3500 480 346
## 335 44 0 si 38 3150 465 335
## 855 43 0 no 38 3600 510 336
## Tipo.parto Ospedale Sesso
## 138 Nat osp2 F
## 205 Nat osp3 M
## 230 Nat osp2 F
## 260 Nat osp1 F
## 335 Nat osp3 F
## 855 Nat osp3 M
d$outlier_flag <- seq_len(nrow(d)) %in% unique(unlist(outlier_indices))
table(d$outlier_flag) # numero totale di outliers
##
## FALSE TRUE
## 2144 356
sapply(outlier_indices, length) # outliers divisi per colonna (N.B.: potrebbero esserci dei valori incrociati)
## Anni.madre N.gravidanze Gestazione Peso Lunghezza Cranio
## 13 246 67 69 59 48
L’algoritmo ha identificato 356 outliers. Tuttavia, operando in ambito sanitario e grazie alla tabella degli indici statistici, si è deciso di rimuovere esclusivamente gli outliers associati alla variabile Anni.madre e di mantenere i restanti in quanto potrebbero essere legati a casi clinici rari che necessitano di un’analisi dedicata.
N.B.: La variabile Numero di gravidanze presenta unità statistiche con valore 0 pertanto è necessario indagare sul suo significato. Si è deciso di mantenerne i valori anomali nel dataset in quanto è stata interpretata come numero di gravidanze precedenti al parto corrente.
cols <- c("Anni.madre")
remove_outliers <- function(df, col) {
Q1 <- quantile(df[[col]], 0.25, na.rm = TRUE)
Q3 <- quantile(df[[col]], 0.75, na.rm = TRUE)
IQR <- Q3 - Q1
lower <- Q1 - 1.5 * IQR
upper <- Q3 + 1.5 * IQR
df[df[[col]] >= lower & df[[col]] <= upper, ]
}
for (c in cols) {
d <- remove_outliers(d, c)
}
Ripeto l’analisi descrittiva sul dataset pulito
cols <- c("Anni.madre", "N.gravidanze", "Gestazione", "Peso", "Lunghezza", "Cranio")
desc_new <- data.frame(
media = sapply(d[cols], mean, na.rm = TRUE),
median = sapply(d[cols], median, na.rm = TRUE),
min = sapply(d[cols], min, na.rm = TRUE),
max = sapply(d[cols], max, na.rm = TRUE),
qtl.25 = sapply(d[cols], quantile, probs=0.25,na.rm = TRUE),
qtl.75 = sapply(d[cols], quantile, probs=0.75,na.rm = TRUE),
sd = sapply(d[cols], sd, na.rm = TRUE),
skewness = sapply(d[cols], skewness, na.rm = TRUE),
kurtosi = sapply(d[cols], function(x) kurtosis(x, na.rm=TRUE)-3)
)
kable(desc_new)
| media | median | min | max | qtl.25 | qtl.75 | sd | skewness | kurtosi | |
|---|---|---|---|---|---|---|---|---|---|
| Anni.madre | 28.1523924 | 28 | 15 | 42 | 25 | 32 | 5.124800 | 0.1095618 | -0.2605367 |
| N.gravidanze | 0.9798955 | 1 | 0 | 12 | 0 | 1 | 1.277788 | 2.5229692 | 11.1167651 |
| Gestazione | 38.9835143 | 39 | 25 | 43 | 38 | 40 | 1.869681 | -2.0724822 | 8.2940113 |
| Peso | 3284.6328910 | 3300 | 830 | 4930 | 2990 | 3620 | 525.323328 | -0.6470005 | 2.0357109 |
| Lunghezza | 494.7426618 | 500 | 310 | 565 | 480 | 510 | 26.350546 | -1.5201400 | 6.4988027 |
| Cranio | 340.0096502 | 340 | 235 | 390 | 330 | 350 | 16.411686 | -0.7928552 | 2.9614758 |
L’età delle madri presenta una distribuzione pressoché simmetrica (skewness prossima a zero) e una moderata dispersione, come indicato dalla deviazione standard.
Il numero medio di gravidanze mostra una lieve asimmetria positiva, segnalando la presenza di alcune madri con un numero di gravidanze superiore alla media.
La durata della gestazione presenta una media intorno alle 39 settimane, con una bassa variabilità: ciò suggerisce che la maggior parte dei parti avviene a termine. I valori minimi e massimi permettono di identificare i casi di nascita prematura e post-termine.
Il peso dei neonati ha una distribuzione leggermente asimmetrica a sinistra, tipica di variabili biologiche soggette a limiti inferiori fisiologici. La deviazione standard indica una moderata dispersione, coerente con la variabilità osservata nei neonati sani.
Le misure antropometriche (lunghezza e diametro cranico) mostrano valori medi compatibili con la letteratura clinica. La bassa kurtosi e skewness indicano una distribuzione vicina alla normalità, confermando che i dati non presentano valori estremi o anomali evidenti.
Valuto le frequenze relative di ciascuna variabile qualitativa
perc <- function(var) {
tab <- prop.table(table(var)) * 100
round(tab, 2)
}
# Distribuzione per Ospedale
kable(perc(d$Ospedale))
| var | Freq |
|---|---|
| osp1 | 32.65 |
| osp2 | 33.94 |
| osp3 | 33.41 |
# Distribuzione per Sesso
kable(perc(d$Sesso))
| var | Freq |
|---|---|
| F | 50.26 |
| M | 49.74 |
# Distribuzione per Fumo
kable(perc(d$Fumatrici))
| var | Freq |
|---|---|
| no | 95.86 |
| si | 4.14 |
# Distribuzione per tipo di parto
kable(perc(d$Tipo.parto))
| var | Freq |
|---|---|
| Ces | 29.19 |
| Nat | 70.81 |
ggplot(d, aes(x = Peso)) +
geom_histogram(aes(y=..density..), bins = 30) +
geom_density(color="red") +
labs(title="Distribuzione del peso alla nascita", x="Peso (grammi)", y="Densità")
Il grafico mostra la distribuzione del peso dei neonati alla
nascita.
L’istogramma rappresenta la frequenza relativa dei valori di peso,
mentre la curva rossa sovrapposta indica la densità stimata.
Osservando la forma della distribuzione, si nota che essa è
approssimativamente simmetrica, con un picco intorno ai
3200–3300 grammi, valore coerente con la media
calcolata in precedenza.
La coda destra leggermente più lunga suggerisce una lieve asimmetria
negativa (skewness < 0), coerente con la presenza di alcuni neonati
con peso inferiore alla media, probabilmente dovuto a nascite premature
o a condizioni materne particolari.
ggplot(d, aes(x = Sesso, y = Peso)) +
geom_boxplot() +
labs(title="Peso per sesso", x="Sesso", y="Peso (grammi)")
Il boxplot mostra la distribuzione del peso alla nascita suddivisa
per sesso. Osservando il grafico, si nota che i neonati di sesso
maschile (M) presentano in media un peso leggermente superiore
rispetto alle neonate (F).
La mediana e la posizione della scatola risultano infatti spostate verso
valori più alti nei maschi, confermando una differenza di peso tipica e
coerente con la letteratura clinica.
La variabilità interna (indicata dall’ampiezza del box) appare simile tra i due gruppi, ma si osserva la presenza di outlier in entrambe le categorie.
ggplot(d, aes(x = Ospedale, fill = Tipo.parto)) +
geom_bar(position="fill") +
labs(title="Composizione % tipo di parto per ospedale",
x="Ospedale", y="Proporzione") +
guides(fill = guide_legend(title="Tipo di parto"))
Il grafico mostra la distribuzione percentuale dei tipi di parto (naturale e cesareo) nei tre ospedali analizzati. Osservando il grafico, si nota che la composizione è piuttosto simile tra le tre strutture, con una prevalenza di parti naturali in tutti gli ospedali.
Queste ed altre considerazioni verranno saggiate nella sezione successiva tramite opportuni test statistici.
L’obiettivo è verificare se c’è associazione tra le due variabili categoriche oppure, in altri termini, esaminare se la distribuzione del tipo di parto (naturale o cesareo) cambia al variare dell’ospedale. Per condurre quest’analisi il test statistico più indicato è il test χ² di indipendenza
Ipotesi
\(H_0\): tipo di parto e ospedale sono indipendenti (stesse proporzioni di cesarei in tutti gli ospedali).
\(H_1\): esiste associazione (almeno un ospedale ha proporzione diversa).
tab_parto_osp <- table(Ospedale = d$Ospedale, Parto = d$Tipo.parto)
kable(tab_parto_osp)
| Ces | Nat | |
|---|---|---|
| osp1 | 240 | 572 |
| osp2 | 254 | 590 |
| osp3 | 232 | 599 |
test_chi <- chisq.test(tab_parto_osp, correct = FALSE)
print(test_chi)
##
## Pearson's Chi-squared test
##
## data: tab_parto_osp
## X-squared = 1.0374, df = 2, p-value = 0.5953
Siccome p-value = 0,5953 > 0,05 non rifiuto \(H_0\): i dati non forniscono evidenza di differenze nelle percentuali di parti cesarei tra i tre ospedali.
Concludiamo che il campione non fornisce alcuna differenza statisticamente rilevante nella distribuzione del tipo di parto tra i tre ospedali.
L’obiettivo è quello di confrontare la media di due variabili quantitative continue (peso e lunghezza) di un campione con dei valori noti di riferimento nel caso in cui la varianza della popolazione non è nota. Si è scelto pertanto di condurre il t-test per un campione per ciascuna variabile.
Ipotesi
\(H_0\): \(\mu = \mu_0\) il campione rappresenta la popolazione di riferimento
\(H_1\): \(\mu \not= \mu_0\) la media del campione è diversa da quella di riferimento
I valori medi della popolazione sono 3300 g e 500 mm (fonte: Ospedale Bambino Gesù)
mu_peso_pop <- 3300
mu_lung_pop <- 500
t_peso <- t.test(d$Peso, mu = mu_peso_pop)
t_lung <- t.test(d$Lunghezza, mu = mu_lung_pop)
print(t_peso)
##
## One Sample t-test
##
## data: d$Peso
## t = -1.4588, df = 2486, p-value = 0.1447
## alternative hypothesis: true mean is not equal to 3300
## 95 percent confidence interval:
## 3263.977 3305.289
## sample estimates:
## mean of x
## 3284.633
print(t_lung)
##
## One Sample t-test
##
## data: d$Lunghezza
## t = -9.9498, df = 2486, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 500
## 95 percent confidence interval:
## 493.7065 495.7788
## sample estimates:
## mean of x
## 494.7427
Peso
Siccome p-value = 0,1447 > 0,05 non rifiuto \(H_0\): il peso medio dei neonati nel campione (3284,6 g) non differisce in modo significativo dal valore medio della popolazione (3300 g) quindi il campione può essere considerato rappresentativo della popolazione per quanto riguarda il peso.
Lunghezza
Siccome p-value = 2,2e-16 < 0,05 rifiuto \(H_0\): la lunghezza media dei neonati nel campione (494,7 mm) è significativamente inferiore rispetto alla popolazione di riferimento (500 mm, circa 5 mm in meno). Siccome si tratta di una differenza statisticamente significativa ma piccola in termini pratici si è ritenuto opportuno considerare questo risultato marginale nelle valutazioni successive.
L’obiettivo è quello di verificare se le misure antropometriche (descritte dalle variabili quantitative continue Peso, Lunghezza e Cranio) sono significativamente diverse tra i due sessi. Poichè la variabile di confronto ha due categorie e i campioni sono indipendenti (ogni neonato appartiene ad un solo gruppo, maschi o femmine) si è scelto di utilizzare il t-test per campioni indipendenti
Ipotesi
\(H_0\): \(\mu_\text{maschi} = \mu_\text{femmine}\) nessuna differenza di media tra i sessi
\(H_1\): \(\mu_\text{maschi} \not= \mu_\text{femmine}\) esiste una differenza di media tra i sessi
t_peso_sesso <- t.test(Peso ~ Sesso, data = d)
t_lung_sesso <- t.test(Lunghezza ~ Sesso, data = d)
t_cranio_sesso <- t.test(Cranio ~ Sesso, data = d)
print(t_peso_sesso)
##
## Welch Two Sample t-test
##
## data: Peso by Sesso
## t = -12.05, df = 2478.2, 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:
## -286.8803 -206.5763
## sample estimates:
## mean in group F mean in group M
## 3161.914 3408.642
print(t_lung_sesso)
##
## Welch Two Sample t-test
##
## data: Lunghezza by Sesso
## t = -9.4851, df = 2447.5, 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:
## -11.877170 -7.807573
## sample estimates:
## mean in group F mean in group M
## 489.8472 499.6896
print(t_cranio_sesso)
##
## Welch Two Sample t-test
##
## data: Cranio by Sesso
## t = -7.2915, df = 2478.2, p-value = 4.102e-13
## alternative hypothesis: true difference in means between group F and group M is not equal to 0
## 95 percent confidence interval:
## -6.025036 -3.471203
## sample estimates:
## mean in group F mean in group M
## 337.6480 342.3961
Siccome per tutte le misure antropometrice vale p-value < 0,05 rifiuto \(H_0\): tutte le differenze tra i sessi sono statisticamente significative. In media, i neonati maschi presantano valori maggiori in tutte le misure antropometriche considerate: peso, lunghezza e diametro craniale.
Prima di procedere con la costruzione del modello di regressione lineare multipla, è fondamentale esplorare le relazioni tra le variabili quantitative presenti nel dataset.
A tal fine, è stata realizzata una matrice di dispersione che consente di osservare contemporaneamente:
la forma delle relazioni bivariate tra le variabili (nei pannelli superiori);
i coefficienti di correlazione lineare di Pearson (nei pannelli inferiori).
Questa analisi preliminare è utile per:
verificare la presenza di relazioni lineari tra la variabile dipendente (Peso) e le variabili esplicative;
individuare collinearità elevate tra regressori, che potrebbero compromettere la stabilità del modello;
evidenziare eventuali relazioni spurie o non lineari.
d <- d[,1:10] #rimuovo eventuali colonne create precedentemente
panel.cor <- function(x, y, digits = 2, prefix = "", cex.cor, ...)
{
par(usr = c(0, 1, 0, 1))
r <- abs(cor(x, y))
txt <- format(c(r, 0.123456789), digits = digits)[1]
txt <- paste0(prefix, txt)
if(missing(cex.cor)) cex.cor <- 0.8/strwidth(txt)
text(0.5, 0.5, txt, cex = cex.cor * r)
}
pairs(d, upper.panel = panel.smooth, lower.panel = panel.cor)
Dalla matrice di dispersione si osservano alcune relazioni interessanti:
Gestazione e Peso mostrano una correlazione positiva (r ≈ 0.59): all’aumentare delle settimane di gestazione aumenta anche il peso del neonato, come atteso biologicamente.
Lunghezza e Peso (r ≈ 0.80) e Cranio e Peso (r ≈ 0.70) risultano anch’esse fortemente correlate, indicando che le misure antropometriche crescono insieme in modo coerente.
Le variabili Anni.madre e N.gravidanze non presentano relazioni lineari evidenti con il peso suggerendo un effetto indiretto o non lineare.
Le variabili categoriche (Sesso, Fumatrici, Tipo parto, Ospedale) non mostrano relazioni lineari nel grafico ma verranno considerate nel modello tramite codifica dummy.
Si evidenzia quindi un insieme di forti correlazioni tra variabili antropometriche, che sarà importante considerare nel modello di regressione per evitare ridondanze o collinearità.
Si procede con la costruzione di un modello di regressione lineare multipla con l’obiettivo di stimare il peso alla nascita del neonato.
Tale approccio consente di quantificare l’effetto simultaneo di più fattori sulla variabile risposta, tenendo conto delle possibili relazioni e interazioni tra di essi.
In particolare, il modello adottato segue la forma generale:
\[ \textit{Peso} = \beta_0 + \beta_1 X_{1} + \beta_2 X_{2} + \dots + \beta_k X_{k} + \varepsilon \]
dove:
\(\textit{Peso}\) è la variabile dipendente (peso alla nascita, in grammi);
\(X_i\) sono le variabili indipendenti;
\(\beta_0\) è l’intercetta del modello;
\(\beta_i\) rappresenta il coefficiente di regressione associato alla variabile \(X_i\);
\(\varepsilon\) rappresenta il termine di errore casuale, che si assume distribuito normalmente, con media nulla e varianza costante.
mod1 <- lm(Peso ~ ., data = d)
summary(mod1)
##
## Call:
## lm(formula = Peso ~ ., data = d)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1125.81 -181.68 -15.02 161.00 2613.60
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6732.0237 141.8849 -47.447 < 2e-16 ***
## Anni.madre 0.8754 1.1708 0.748 0.4547
## N.gravidanze 11.5221 4.6946 2.454 0.0142 *
## Fumatricisi -33.3922 27.6949 -1.206 0.2280
## Gestazione 32.3695 3.8274 8.457 < 2e-16 ***
## Lunghezza 10.3003 0.3014 34.173 < 2e-16 ***
## Cranio 10.4639 0.4281 24.443 < 2e-16 ***
## Tipo.partoNat 30.3139 12.1145 2.502 0.0124 *
## Ospedaleosp2 -10.1785 13.4854 -0.755 0.4505
## Ospedaleosp3 27.7962 13.5394 2.053 0.0402 *
## SessoM 78.5901 11.2117 7.010 3.07e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 274.1 on 2476 degrees of freedom
## Multiple R-squared: 0.7288, Adjusted R-squared: 0.7277
## F-statistic: 665.4 on 10 and 2476 DF, p-value: < 2.2e-16
\(R^2_\text{adj}=\) 0.728 indica che circa il 72.9% della variabilità del peso dei neonati è spiegata dalle variabili incluse nel modello;
Le variabili Gestazione, Lunghezza, Cranio e Sesso risultano fortemente significative e biologicamente coerenti: indicano che la crescita fetale e il sesso maschile influenzano positivamente il peso.
N.gravidanze e Tipo di parto mostrano effetti modesti ma significativi, mentre l’età della madre e il fumo non risultano influenti suggerendo che potrebbero avere effetti non lineari o di interazione.
Verifichiamo ora le principali assunzioni teoriche del modello lineare classico, al fine di garantire la validità delle inferenze statistiche e la correttezza delle stime dei coefficienti.
par(mfrow=c(2,2))
plot(mod1)
shapiro.test(residuals(mod1)) # normalità dei residui
##
## Shapiro-Wilk normality test
##
## data: residuals(mod1)
## W = 0.97397, p-value < 2.2e-16
lmtest::bptest(mod1) # omoschedasticità
##
## studentized Breusch-Pagan test
##
## data: mod1
## BP = 93.666, df = 10, p-value = 1.001e-15
lmtest::dwtest(mod1) # indipendenza degli errori
##
## Durbin-Watson test
##
## data: mod1
## DW = 1.9583, p-value = 0.1494
## alternative hypothesis: true autocorrelation is greater than 0
car::vif(mod1) # multicollinearità
## GVIF Df GVIF^(1/(2*Df))
## Anni.madre 1.191168 1 1.091406
## N.gravidanze 1.190548 1 1.091122
## Fumatrici 1.007852 1 1.003918
## Gestazione 1.694200 1 1.301614
## Lunghezza 2.087152 1 1.444698
## Cranio 1.633153 1 1.277949
## Tipo.parto 1.004065 1 1.002030
## Ospedale 1.004509 2 1.001125
## Sesso 1.040108 1 1.019857
L’analisi grafica dei residuals vs fitted values mostra una dispersione sostanzialmente casuale attorno allo zero, suggerendo che la relazione tra la variabile dipendente e i regressori può essere approssimata adeguatamente da un modello lineare. Tuttavia, è possibile notare una lieve curvatura nei valori estremi che suggerisce una possibile componente non lineare marginale.
Il test di Shapiro–Wilk ha restituito un valore di \(W =\) 0.9739678 con \(\textit{p-value} =\) 6.9573781^{-21}, suggerendo il rifiuto dell’ipotesi di normalità. Anche il grafico Q–Q residuals mostra deviazioni nelle code, in particolare nei valori più alti di peso. Nonostante ciò, data l’elevata numerosità campionaria (\(n \approx 2500\)), l’impatto di tale deviazione sull’attendibilità delle stime risulta limitato per effetto del teorema del limite centrale.
Il test di Breusch–Pagan ha prodotto un valore di \(BP =\) 93.6657944 (df = 10) con \(\textit{p-value} =\) 1.0013744^{-15}, indicando la presenza di una leggera eteroschedasticità. I grafici Scale–Location e Residuals vs Fitted mostrano infatti una lieve crescita della varianza dei residui per valori elevati di peso stimato.
Il test di Durbin–Watson (\(DW =\) 1.9583054, \(\textit{p-value} =\) 0.1493913) non mostra evidenze di autocorrelazione, pertanto l’ipotesi di indipendenza degli errori può essere considerata soddisfatta.
I valori del Variance Inflation Factor (VIF) risultano tutti inferiori a 2, ben al di sotto della soglia critica di 5 raccomandata in letteratura. Ciò indica che non sono presenti forti correlazioni tra le variabili indipendenti.
Nel complesso, le assunzioni fondamentali del modello lineare risultano soddisfatte in misura accettabile. Le lievi violazioni della normalità e dell’omoschedasticità dei residui non compromettono la validità inferenziale del modello, ma suggeriscono che modelli alternativi potrebbero migliorare ulteriormente l’adattamento ai dati.
Si procede costruendo un modello completo che includa anche termini di secondo ordine e interazioni tra variabili suggerite dall’osservazione della matrice di correlazione.
L’obiettivo è verificare se la relazione tra il peso neonatale e le variabili esplicative segua effettivamente un andamento lineare o se siano presenti effetti non lineari o combinati che migliorano la capacità predittiva del modello.
d <- d[,1:10]
mod_full <- lm(Peso ~
Gestazione + Anni.madre + N.gravidanze + Lunghezza + Cranio
+ Fumatrici + Sesso + Tipo.parto
+ I(Gestazione^2) + I(Anni.madre^2) + I(N.gravidanze^2)
+ I(Lunghezza^2) + I(Cranio^2)
+ Gestazione:Lunghezza + Gestazione:Cranio
+ Lunghezza:Cranio + Gestazione:Fumatrici
+ Gestazione:Sesso,
data=d)
summary(mod_full)
##
## Call:
## lm(formula = Peso ~ Gestazione + Anni.madre + N.gravidanze +
## Lunghezza + Cranio + Fumatrici + Sesso + Tipo.parto + I(Gestazione^2) +
## I(Anni.madre^2) + I(N.gravidanze^2) + I(Lunghezza^2) + I(Cranio^2) +
## Gestazione:Lunghezza + Gestazione:Cranio + Lunghezza:Cranio +
## Gestazione:Fumatrici + Gestazione:Sesso, data = d)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1137.91 -178.44 -11.94 163.32 1325.39
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -158.13507 1210.25632 -0.131 0.89605
## Gestazione 152.71131 76.07563 2.007 0.04482 *
## Anni.madre 11.77320 8.91444 1.321 0.18673
## N.gravidanze 33.27562 8.32437 3.997 6.59e-05 ***
## Lunghezza -3.21543 5.93314 -0.542 0.58791
## Cranio -24.44760 10.23996 -2.387 0.01704 *
## Fumatricisi 722.47916 742.40880 0.973 0.33057
## SessoM -145.38883 234.17649 -0.621 0.53475
## Tipo.partoNat 30.37478 11.78236 2.578 0.01000 **
## I(Gestazione^2) -4.48544 1.63072 -2.751 0.00599 **
## I(Anni.madre^2) -0.20610 0.15619 -1.320 0.18710
## I(N.gravidanze^2) -3.34706 1.28674 -2.601 0.00935 **
## I(Lunghezza^2) 0.05596 0.00651 8.596 < 2e-16 ***
## I(Cranio^2) 0.05100 0.01886 2.705 0.00689 **
## Gestazione:Lunghezza -0.29341 0.19719 -1.488 0.13688
## Gestazione:Cranio 1.10252 0.20933 5.267 1.51e-07 ***
## Lunghezza:Cranio -0.08682 0.01672 -5.193 2.23e-07 ***
## Gestazione:Fumatricisi -19.21502 18.89188 -1.017 0.30920
## Gestazione:SessoM 5.66238 5.99860 0.944 0.34529
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 266 on 2468 degrees of freedom
## Multiple R-squared: 0.7455, Adjusted R-squared: 0.7436
## F-statistic: 401.5 on 18 and 2468 DF, p-value: < 2.2e-16
Il modello presenta un \(R^2_\text{adj}=\) 0.744 indicando un ottimo livello di adattamento ai dati.
Per identificare il modello più parsimonioso applichiamo due criteri di selezione automatica:
Akaike Information Criterion (AIC): penalizza meno i modelli complessi;
Bayesian Information Criterion (BIC): favorisce modelli più semplici.
mod_aic <- stepAIC(mod_full, direction = "both", k = 2, trace =F)
summary(mod_aic)
##
## Call:
## lm(formula = Peso ~ Gestazione + N.gravidanze + Lunghezza + Cranio +
## Sesso + Tipo.parto + I(Gestazione^2) + I(N.gravidanze^2) +
## I(Lunghezza^2) + I(Cranio^2) + Gestazione:Lunghezza + Gestazione:Cranio +
## Lunghezza:Cranio, data = d)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1171.90 -177.21 -11.02 163.71 1318.86
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.989e+01 1.195e+03 0.042 0.96671
## Gestazione 1.486e+02 7.529e+01 1.973 0.04856 *
## N.gravidanze 3.249e+01 7.876e+00 4.126 3.82e-05 ***
## Lunghezza -3.537e+00 5.924e+00 -0.597 0.55048
## Cranio -2.408e+01 1.023e+01 -2.354 0.01867 *
## SessoM 7.421e+01 1.093e+01 6.787 1.43e-11 ***
## Tipo.partoNat 3.016e+01 1.177e+01 2.564 0.01042 *
## I(Gestazione^2) -4.492e+00 1.613e+00 -2.784 0.00541 **
## I(N.gravidanze^2) -3.311e+00 1.271e+00 -2.605 0.00925 **
## I(Lunghezza^2) 5.604e-02 6.505e-03 8.614 < 2e-16 ***
## I(Cranio^2) 5.083e-02 1.884e-02 2.698 0.00703 **
## Gestazione:Lunghezza -2.811e-01 1.969e-01 -1.428 0.15345
## Gestazione:Cranio 1.104e+00 2.091e-01 5.282 1.39e-07 ***
## Lunghezza:Cranio -8.742e-02 1.671e-02 -5.231 1.83e-07 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 266 on 2473 degrees of freedom
## Multiple R-squared: 0.7449, Adjusted R-squared: 0.7436
## F-statistic: 555.5 on 13 and 2473 DF, p-value: < 2.2e-16
n <- nrow(d)
mod_bic <- stepAIC(mod_full, direction = "both", k = log(n), trace =F)
summary(mod_bic)
##
## Call:
## lm(formula = Peso ~ Gestazione + N.gravidanze + Lunghezza + Cranio +
## Sesso + I(Gestazione^2) + I(Lunghezza^2) + I(Cranio^2) +
## Gestazione:Cranio + Lunghezza:Cranio, data = d)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1168.08 -182.32 -11.74 168.64 1319.67
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.651e+02 1.193e+03 -0.138 0.88993
## Gestazione 1.787e+02 7.449e+01 2.399 0.01652 *
## N.gravidanze 1.497e+01 4.237e+00 3.532 0.00042 ***
## Lunghezza -6.958e+00 5.669e+00 -1.227 0.21982
## Cranio -2.102e+01 1.012e+01 -2.077 0.03790 *
## SessoM 7.366e+01 1.095e+01 6.724 2.19e-11 ***
## I(Gestazione^2) -6.272e+00 1.034e+00 -6.068 1.49e-09 ***
## I(Lunghezza^2) 5.028e-02 5.049e-03 9.960 < 2e-16 ***
## I(Cranio^2) 5.575e-02 1.854e-02 3.006 0.00267 **
## Gestazione:Cranio 1.012e+00 2.062e-01 4.907 9.86e-07 ***
## Lunghezza:Cranio -9.292e-02 1.581e-02 -5.877 4.75e-09 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 266.6 on 2476 degrees of freedom
## Multiple R-squared: 0.7434, Adjusted R-squared: 0.7424
## F-statistic: 717.3 on 10 and 2476 DF, p-value: < 2.2e-16
AIC(mod_full, mod_aic, mod_bic)
## df AIC
## mod_full 20 34851.12
## mod_aic 15 34846.30
## mod_bic 12 34855.20
BIC(mod_full, mod_aic, mod_bic)
## df BIC
## mod_full 20 34967.50
## mod_aic 15 34933.58
## mod_bic 12 34925.03
Il confronto tra i criteri indica che:
Il modello AIC ottiene il valore di AIC più basso, quindi è il preferito in termini di capacità predittiva e adattamento ai dati.
Il modello BIC, pur leggermente meno performante in AIC, presenta un BIC più basso rispetto al modello completo, risultando più parsimonioso e interpretabile.
mod_star <- mod_bic
In conclusione, il modello selezionato secondo BIC rappresenta un compromesso ottimale tra accuratezza statistica e semplicità interpretativa.
\(\text{RMSE} = 266.6 \, g\) significa che, in media, le previsioni del modello differiscono di circa 266 grammi dal peso reale del neonato; per esempio, rispetto a una media del peso intorno a 3200 g, rappresenta un errore medio inferiore al 10%, quindi piuttosto buono per un modello clinico.
\(R^2_\text{adj}=0.7424\) significa che circa il 74% della variabilità del peso neonatale è spiegato dalle variabili incluse nel modello.
È interessante osservare che nel modello selezionato da BIC compaiono solo 5 dei 9 possibili regressori, in particolare sono state rimosse le variabili Anni.madre e Fumatrici suggerendo che il loro impatto sul peso neonatale è molto meno significativo di quanto si potrebbe ipotizzare.
Sottoponiamo il modello così selezionato alla verifica delle assunzioni a cui abbiamo sottoposto i modelli precedenti con l’obiettivo di confermare la bontà delle stime e l’adeguatezza del modello finale in termini inferenziali e predittivi.
par(mfrow=c(2,2))
plot(mod_star)
I grafici mostrano:
una distribuzione dei residui centrata attorno a zero, senza pattern evidenti che indichino relazioni non lineari;
una varianza dei residui quasi costante, con un leggero aumento nella parte destra del grafico;
il Q–Q plot mostra solo piccole deviazioni nelle code, indice di una buona approssimazione alla normalità;
nessun punto di leverage particolarmente influente, confermando l’assenza di osservazioni anomale che distorcano il modello.
shapiro.test(mod_star$residuals)
##
## Shapiro-Wilk normality test
##
## data: mod_star$residuals
## W = 0.99095, p-value = 2.181e-11
plot(density(residuals(mod_star)))
lmtest::bptest(mod_star)
##
## studentized Breusch-Pagan test
##
## data: mod_star
## BP = 41.138, df = 10, p-value = 1.067e-05
lmtest::dwtest(mod_star)
##
## Durbin-Watson test
##
## data: mod_star
## DW = 1.9644, p-value = 0.187
## alternative hypothesis: true autocorrelation is greater than 0
car::vif(mod_star, type="predictor")
## GVIFs computed for predictors
## GVIF Df GVIF^(1/(2*Df)) Interacts With
## Gestazione 1681.088593 5 2.101644 I(Gestazione^2), Cranio
## N.gravidanze 1.024914 1 1.012380 --
## Lunghezza 1735.975208 5 2.108407 I(Lunghezza^2), Cranio
## Cranio 1.073263 8 1.004429 I(Cranio^2), Gestazione, Lunghezza
## Sesso 1.049274 1 1.024341 --
## Other Predictors
## Gestazione N.gravidanze, Lunghezza, Sesso
## N.gravidanze Gestazione, Lunghezza, Cranio, Sesso
## Lunghezza Gestazione, N.gravidanze, Sesso
## Cranio N.gravidanze, Sesso
## Sesso Gestazione, N.gravidanze, Lunghezza, Cranio
Il test di Shapiro–Wilk (\(W =\) 0.9909533, \(\textit{p-value} =\) 2.1807516^{-11}) evidenzia una lieve deviazione dalla normalità teorica, ma il grafico di densità mostra una distribuzione simmetrica e centrata attorno a zero. Considerata la numerosità campionaria elevata (\(n \approx 2500\)), tale deviazione non compromette la validità del modello.
Il test di Breusch–Pagan (\(BP =\) 41.1379173, \(\textit{p-value} =\) 1.0667069^{-5}) segnala una lieve eterogeneità della varianza, ma molto ridotta rispetto ai modelli precedenti. La distribuzione dei residui nei grafici Residuals vs Fitted e Scale–Location appare più omogenea e stabile.
Il test di Durbin–Watson (\(DW =\) 1.9643581, \(\textit{p-value} =\) 0.1870408) non fornisce evidenze di autocorrelazione, quindi l’ipotesi di indipendenza può ritenersi soddisfatta.
I valori del GVIF, corretti per i gradi di libertà, sono tutti prossimi a 1, ben al di sotto della soglia critica di 5. Ciò conferma che le variabili incluse non risultano eccessivamente correlate tra loro.
Per completare la valutazione del modello finale, si conduce un’analisi dei punti influenti e degli outlier, essenziale per verificare che la stima dei coefficienti non sia eccessivamente condizionata da poche osservazioni anomale.
lev <- hatvalues(mod_star)
plot(lev, main = "Leverage dei punti", ylab = "Leverage")
abline(h = 2*mean(lev), col = "red")
Il grafico dei valori di leverage mostra la maggior parte delle osservazioni al di sotto della soglia 2h (linea rossa). Solo pochi punti si distinguono come potenzialmente influenti, ma la loro incidenza sul modello risulta marginale. In generale, non emergono casi con leverage eccessivo tali da richiedere esclusione.
stud_res <- rstudent(mod_star)
plot(stud_res, main = "Residuals Studentizzati", ylab = "Valore")
abline(h = c(-2,2), col="red", lty=2)
outlierTest(mod_star)
## rstudent unadjusted p-value Bonferroni p
## 1306 4.978656 6.8434e-07 0.0017019
## 155 4.604442 4.3449e-06 0.0108060
## 1399 -4.403448 1.1107e-05 0.0276230
## 1694 4.396472 1.1467e-05 0.0285190
La maggior parte dei residui studentizzati si distribuisce nell’intervallo [−2,2], mentre solo un numero limitato di punti supera le soglie critiche. Questo suggerisce che la quasi totalità delle osservazioni è ben rappresentata dal modello, con pochi casi anomali isolati.
L’analisi numerica tramite outlierTest() conferma la presenza di quattro osservazioni potenzialmente influenti che, pur risultando statisticamente rilevanti dal test di Bonferroni, il loro effetto complessivo è contenuto, come confermato dalle metriche di influenza.
cook <- cooks.distance(mod_star)
plot(cook, main = "Distanza di Cook", ylab = "Cook's distance")
abline(h = 4/length(cook), col="red", lty=2)
Il grafico della distanza di Cook mostra che la quasi totalità delle osservazioni presenta valori inferiori alla soglia di riferimento. Solo poche unità (coincidenti con quelle già identificate come outlier) presentano valori leggermente più alti e solo una ha una distanza di Cook maggiore di 1, valore che in letteratura è indice di un osservazione altamente influente da indagare attentamente.
out <- outlierTest(mod_star)
outlier_ids <- names(out$rstudent)
outliers_df <- d[outlier_ids, ]
print(outliers_df)
## Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio
## 1306 23 0 no 41 4900 510 352
## 155 30 0 no 36 3610 410 330
## 1399 42 2 no 38 2560 525 349
## 1694 23 1 no 36 3850 460 334
## Tipo.parto Ospedale Sesso
## 1306 Nat osp2 F
## 155 Nat osp1 M
## 1399 Ces osp2 M
## 1694 Ces osp3 F
Osservando gli outliers possiamo concludere che non si tratta di veri e propri valori anomali bensì, trovandosi in un contesto biologico, di eventi clinici da segnalare come casi speciali e in quanto tali possiamo scegliere di mantenerli all’interno del dataset.
Per dimostrare questa scelta costruiamo un nuovo dataset rimuovendo gli outliers e ripetiamo il procedimento di creazione del modello e di selezione delle variabili con BIC.
outlier_ids <- as.numeric(names(out$rstudent))
d_no_out <- d[-outlier_ids, ]
mod_out <- lm(Peso ~
Gestazione + Anni.madre + N.gravidanze + Lunghezza + Cranio
+ Fumatrici + Sesso + Tipo.parto
+ I(Gestazione^2) + I(Anni.madre^2) + I(N.gravidanze^2)
+ I(Lunghezza^2) + I(Cranio^2)
+ Gestazione:Lunghezza + Gestazione:Cranio
+ Lunghezza:Cranio + Gestazione:Fumatrici
+ Gestazione:Sesso,
data=d_no_out)
summary(mod_out)
##
## Call:
## lm(formula = Peso ~ Gestazione + Anni.madre + N.gravidanze +
## Lunghezza + Cranio + Fumatrici + Sesso + Tipo.parto + I(Gestazione^2) +
## I(Anni.madre^2) + I(N.gravidanze^2) + I(Lunghezza^2) + I(Cranio^2) +
## Gestazione:Lunghezza + Gestazione:Cranio + Lunghezza:Cranio +
## Gestazione:Fumatrici + Gestazione:Sesso, data = d_no_out)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1137.25 -178.12 -11.91 163.15 1326.01
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -163.35867 1210.24598 -0.135 0.89264
## Gestazione 155.30684 76.10172 2.041 0.04138 *
## Anni.madre 11.52420 8.91578 1.293 0.19628
## N.gravidanze 33.22873 8.32635 3.991 6.78e-05 ***
## Lunghezza -3.26337 5.93451 -0.550 0.58244
## Cranio -24.58858 10.24091 -2.401 0.01642 *
## Fumatricisi 716.30393 742.40228 0.965 0.33472
## SessoM -152.44417 234.29200 -0.651 0.51533
## Tipo.partoNat 30.26116 11.79745 2.565 0.01037 *
## I(Gestazione^2) -4.62552 1.63538 -2.828 0.00472 **
## I(Anni.madre^2) -0.20239 0.15621 -1.296 0.19522
## I(N.gravidanze^2) -3.33284 1.28688 -2.590 0.00966 **
## I(Lunghezza^2) 0.05543 0.00652 8.502 < 2e-16 ***
## I(Cranio^2) 0.05188 0.01887 2.750 0.00600 **
## Gestazione:Lunghezza -0.27375 0.19787 -1.383 0.16664
## Gestazione:Cranio 1.09757 0.20933 5.243 1.71e-07 ***
## Lunghezza:Cranio -0.08737 0.01672 -5.225 1.89e-07 ***
## Gestazione:Fumatricisi -19.05430 18.89175 -1.009 0.31326
## Gestazione:SessoM 5.85013 6.00189 0.975 0.32980
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 266 on 2464 degrees of freedom
## Multiple R-squared: 0.7456, Adjusted R-squared: 0.7438
## F-statistic: 401.2 on 18 and 2464 DF, p-value: < 2.2e-16
n <- nrow(d_no_out)
mod_bic_out <- stepAIC(mod_out, direction = "both", k = log(n), trace =F)
summary(mod_bic_out)
##
## Call:
## lm(formula = Peso ~ Gestazione + N.gravidanze + Lunghezza + Cranio +
## Sesso + I(Gestazione^2) + I(Lunghezza^2) + I(Cranio^2) +
## Gestazione:Cranio + Lunghezza:Cranio, data = d_no_out)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1168.31 -182.24 -11.35 168.51 1320.27
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.664e+02 1.193e+03 -0.140 0.88904
## Gestazione 1.797e+02 7.449e+01 2.413 0.01590 *
## N.gravidanze 1.494e+01 4.238e+00 3.526 0.00043 ***
## Lunghezza -6.814e+00 5.669e+00 -1.202 0.22948
## Cranio -2.132e+01 1.012e+01 -2.107 0.03525 *
## SessoM 7.394e+01 1.096e+01 6.745 1.90e-11 ***
## I(Gestazione^2) -6.279e+00 1.034e+00 -6.075 1.43e-09 ***
## I(Lunghezza^2) 5.016e-02 5.049e-03 9.935 < 2e-16 ***
## I(Cranio^2) 5.630e-02 1.855e-02 3.036 0.00242 **
## Gestazione:Cranio 1.010e+00 2.062e-01 4.898 1.03e-06 ***
## Lunghezza:Cranio -9.295e-02 1.581e-02 -5.880 4.66e-09 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 266.6 on 2472 degrees of freedom
## Multiple R-squared: 0.7436, Adjusted R-squared: 0.7426
## F-statistic: 716.9 on 10 and 2472 DF, p-value: < 2.2e-16
Confrontando i risultati così ottenuti con i modelli precedenti
concludiamo che la rimozione degli outliers non produce risultati
significativi in quanto i coefficienti e le metriche sono rimasti
pressocchè invariati.
Nel complesso:
i valori di leverage rientrano entro limiti accettabili;
i residui studentizzati evidenziano solo un numero limitato di outlier;
la distanza di Cook conferma l’assenza di osservazioni eccessivamente influenti.
Si può quindi concludere che il modello finale è stabile e robusto, in quanto le stime dei coefficienti non sono condizionate in modo rilevante da singole osservazioni anomale. Il comportamento dei residui e la distribuzione dei punti influenti confermano la buona qualità complessiva del modello selezionato secondo il criterio BIC.
Stima del peso di una neonata con Gestazione e N.gravidanze note
newdata <- data.frame(
Gestazione = 39,
Lunghezza = mean(d$Lunghezza),
Cranio = mean(d$Cranio),
Anni.madre = mean(d$Anni.madre),
N.gravidanze = 2,
Sesso = factor("F", levels = levels(d$Sesso))
)
pr <- predict(mod_star, newdata = newdata, se.fit = TRUE)
pr
## $fit
## 1
## 3245.774
##
## $se.fit
## [1] 9.522485
##
## $df
## [1] 2476
##
## $residual.scale
## [1] 266.6487
ggplot(data = d) +
geom_point(aes(x = Gestazione,
y = Peso,
col = Sesso),
position = "jitter", alpha = 0.2) +
geom_smooth(aes(x = Gestazione,
y = Peso,
col = Sesso),
se = FALSE, method = "lm", linewidth = 1.1) +
labs(title = "Relazione tra settimane di gestazione e peso alla nascita",
x = "Settimane di gestazione",
y = "Peso del neonato (grammi)",
color = "Sesso")+
geom_smooth(aes(x=Gestazione, y=Peso), col="black", se=FALSE, method="lm",linewidth = 1) +
theme_minimal(base_size = 13) +
theme(legend.position = "top")
ggplot(data = d) +
geom_point(aes(x = Gestazione, y = Peso, color = Sesso),
position = "jitter", alpha = 0.2) +
geom_smooth(aes(x = Gestazione, y = Peso, color = Sesso),
se = F, method = "lm", linewidth = 1.1) +
facet_wrap(~ Sesso) +
labs(title = "Relazione tra gestazione e peso per sesso",
x = "Settimane di gestazione",
y = "Peso (g)",
color = "Sesso") +
theme_minimal(base_size = 13) +
theme(legend.position = "top")
Il grafico mostra una relazione fortemente positiva tra il numero di settimane di gestazione e il peso del neonato. Si osserva come, all’aumentare delle settimane di gestazione, il peso alla nascita cresca in modo quasi lineare. Le rette di regressione separate per sesso evidenziano che, a parità di settimane, i maschi tendono a pesare leggermente di più rispetto alle femmine, sebbene la differenza non sia marcata. La retta nera rappresenta la tendenza media generale del campione e conferma che la durata della gravidanza è una delle principali determinanti del peso neonatale, coerentemente con quanto atteso dal punto di vista biologico.
ggplot(data=d) +
geom_boxplot(aes(x=Fumatrici, y=Peso, fill=Fumatrici)) +
labs(title="Distribuzione del peso per fumatrici e non fumatrici",
x="Fumo materno", y="Peso (g)") +
theme_minimal()
Dal boxplot emerge che le madri fumatrici tendono ad avere neonati con peso medio leggermente inferiore rispetto alle non fumatrici. Tuttavia, la sovrapposizione delle due distribuzioni e la presenza di numerosi valori estremi (outlier) suggeriscono che l’effetto del fumo, pur potenzialmente presente, non è particolarmente marcato nel dataset considerato. Per questo motivo, oltre alla scarsa significativà del regressore, nella fase di modellizzazione si è deciso di non includere la variabile “Fumo” nel modello finale, poiché il suo contributo esplicativo al peso neonatale risultava statisticamente debole rispetto ad altre variabili.
ggplot(d, aes(x=Gestazione, y=Peso, col=Fumatrici)) +
geom_point(position="jitter") +
geom_smooth(aes(x=Gestazione, y=Peso, col=Fumatrici), method="lm", se=FALSE) +
geom_smooth(aes(x=Gestazione, y=Peso), method="lm", se=FALSE, col="black", linewidth = 0.5) +
labs(title="Interazione tra settimane di gestazione e fumo sul peso",
x="Settimane di gestazione", y="Peso (g)")
Il grafico mostra l’interazione tra settimane di gestazione e fumo materno rispetto al peso del neonato. Le due rette (per fumatrici e non fumatrici) suggeriscono che i neonati di madri fumatrici hanno in media un peso lievemente inferiore rispetto alla controparte dei non fumatori. Tuttavia, essendo il dataset fortemente sbilanciato a favore delle non fumatrici, la relazione principale (indicata dalla retta nera) si confonda facilmente con quella delle non fumatrici. Questa vicinanza suggerisce che la variabile “Fumatrici” non modifica la pendenza della relazione principale e non aggiunge informazione rilevante al modello confermando la scelta metodologica di escludere il fumo come regressore nel modello finale.
dati <- d
dati$Peso_pred <- predict(mod_star)
ggplot(dati, aes(x=Peso, y=Peso_pred)) +
geom_point(alpha=0.6) +
geom_abline(intercept=0, slope=1, col="red") +
labs(title="Peso osservato vs Peso previsto dal modello",
x="Peso osservato (g)", y="Peso previsto (g)") +
theme_minimal()
ggplot(dati, aes(x=fitted(mod_star), y=residuals(mod_star))) +
geom_point(alpha=0.6) +
geom_hline(yintercept=0, col="red") +
labs(title="Analisi dei residui", x="Valori previsti", y="Residui") +
theme_minimal()
Lo scatterplot confronta i valori di peso osservati nel dataset con quelli previsti dal modello finale. La disposizione dei punti lungo la bisettrice rossa indica un buon allineamento tra osservazioni e previsioni: il modello è in grado di riprodurre accuratamente la variabilità del peso all’interno del campione. Le lievi dispersioni intorno alla linea sono fisiologiche e rappresentano la componente di errore non spiegata dal modello, confermando una buona capacità predittiva complessiva.
Il grafico dei residui in funzione dei valori previsti permette di verificare la validità delle assunzioni del modello lineare. La distribuzione simmetrica e casuale dei residui intorno alla linea orizzontale rossa suggerisce che non vi sono evidenze di eteroschedasticità o di andamenti non lineari. Inoltre, l’assenza di pattern sistematici indica che le assunzioni di linearità e omoschedasticità sono rispettate, e che il modello stimato è statisticamente coerente con i dati osservati.
Il progetto sviluppato per Neonatal Health Solutions ha permesso di costruire un modello statistico affidabile per la previsione del peso neonatale a partire da variabili cliniche materne e perinatali. L’analisi descrittiva preliminare ha fornito un quadro completo delle caratteristiche del campione, evidenziando differenze significative tra i sessi e tra i diversi ospedali.
Il modello di regressione lineare multipla ha confermato l’importanza delle settimane di gestazione come principale fattore predittivo del peso alla nascita, seguita da variabili come il numero di gravidanze e il sesso del neonato. La variabile relativa al fumo materno, pur mostrando una tendenza negativa sul peso, non è risultata statisticamente significativa e per questo non è stata inclusa nel modello finale.
Le metriche di valutazione, come \(R^2\) e RMSE, hanno evidenziato una buona capacità esplicativa del modello, mentre l’analisi dei residui e delle osservazioni influenti ha confermato l’adeguatezza dell’approccio adottato. Le visualizzazioni grafiche hanno inoltre permesso di interpretare in modo chiaro le relazioni tra le variabili, rendendo i risultati facilmente comunicabili anche in contesti clinici.
In conclusione, il modello proposto rappresenta uno strumento predittivo efficace a supporto delle decisioni cliniche, utile per l’individuazione precoce dei neonati a rischio e per la pianificazione ottimale delle risorse ospedaliere.