# Caricamento dei dati
neonati <- read.csv("C:/Users/matma/Desktop/Profession.AI/3) Statistica Inferenziale/Progetto/neonati.csv", stringsAsFactors = FALSE)
# Rinomino le colonne per evitare problemi con i punti
names(neonati) <- c("Eta_madre", "N_gravidanze", "Fumatrice", "Gestazione",
"Peso", "Lunghezza", "Cranio", "Tipo_parto", "Ospedale", "Sesso")
# Conversione delle variabili categoriche in fattori
neonati$Fumatrice <- factor(neonati$Fumatrice, levels = c(0, 1),
labels = c("No", "Si"))
neonati$Tipo_parto <- factor(neonati$Tipo_parto)
neonati$Ospedale <- factor(neonati$Ospedale)
neonati$Sesso <- factor(neonati$Sesso)
# Visualizzazione delle prime righe del dataset
head(neonati) %>%
kbl() %>%
kable_styling(bootstrap_options = c("striped", "hover"))
| Eta_madre | N_gravidanze | Fumatrice | Gestazione | Peso | Lunghezza | Cranio | Tipo_parto | Ospedale | Sesso |
|---|---|---|---|---|---|---|---|---|---|
| 26 | 0 | No | 42 | 3380 | 490 | 325 | Nat | osp3 | M |
| 21 | 2 | No | 39 | 3150 | 490 | 345 | Nat | osp1 | F |
| 34 | 3 | No | 38 | 3640 | 500 | 375 | Nat | osp2 | M |
| 28 | 1 | No | 41 | 3690 | 515 | 365 | Nat | osp2 | M |
| 20 | 0 | No | 38 | 3700 | 480 | 335 | Nat | osp3 | F |
| 32 | 0 | No | 40 | 3200 | 495 | 340 | Nat | osp2 | F |
# Riepilogo della struttura del dataset
str(neonati)
## 'data.frame': 2500 obs. of 10 variables:
## $ Eta_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 ...
## $ Fumatrice : Factor w/ 2 levels "No","Si": 1 1 1 1 1 1 1 1 1 1 ...
## $ 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 : Factor w/ 2 levels "Ces","Nat": 2 2 2 2 2 2 2 2 1 1 ...
## $ Ospedale : Factor w/ 3 levels "osp1","osp2",..: 3 1 2 2 3 2 3 1 2 2 ...
## $ Sesso : Factor w/ 2 levels "F","M": 2 1 2 2 1 1 1 2 1 1 ...
# Verifica di valori mancanti
missing_values <- colSums(is.na(neonati))
print(missing_values)
## Eta_madre N_gravidanze Fumatrice Gestazione Peso Lunghezza
## 0 0 0 0 0 0
## Cranio Tipo_parto Ospedale Sesso
## 0 0 0 0
# Statistiche descrittive
summary(neonati)
## Eta_madre N_gravidanze Fumatrice Gestazione Peso
## Min. : 0.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.16 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
## Lunghezza Cranio Tipo_parto Ospedale Sesso
## Min. :310.0 Min. :235 Ces: 728 osp1:816 F:1256
## 1st Qu.:480.0 1st Qu.:330 Nat:1772 osp2:849 M:1244
## Median :500.0 Median :340 osp3:835
## Mean :494.7 Mean :340
## 3rd Qu.:510.0 3rd Qu.:350
## Max. :565.0 Max. :390
# Visualizzazione della distribuzione delle variabili numeriche
numeric_vars <- neonati %>%
select(Eta_madre, N_gravidanze, Gestazione, Peso, Lunghezza, Cranio)
# Funzione per creare gli istogrammi
plot_histogram <- function(data, var_name) {
ggplot(data, aes_string(x = var_name)) +
geom_histogram(aes(y = ..density..), fill = "steelblue", color = "white", bins = 30) +
geom_density(color = "red") +
labs(title = paste("Distribuzione di", var_name), x = var_name, y = "Densità") +
theme_minimal()
}
# Creazione degli istogrammi per ogni variabile numerica
histogram_plots <- lapply(names(numeric_vars), function(var) plot_histogram(numeric_vars, var))
# Visualizzazione degli istogrammi
wrap_plots(histogram_plots, ncol = 2)
# Boxplot per identificare outlier
boxplot_plots <- lapply(names(numeric_vars), function(var) {
ggplot(numeric_vars, aes_string(y = var)) +
geom_boxplot(fill = "steelblue") +
labs(title = paste("Boxplot di", var), y = var) +
theme_minimal() +
coord_flip()
})
wrap_plots(boxplot_plots, ncol = 2)
# Analisi delle variabili categoriche
categorical_vars <- neonati %>%
select(Fumatrice, Tipo_parto, Ospedale, Sesso)
# Funzione per creare i grafici a barre
plot_bar <- function(data, var_name) {
ggplot(data, aes_string(x = var_name, fill = var_name)) +
geom_bar() +
labs(title = paste("Distribuzione di", var_name), x = var_name, y = "Conteggio") +
theme_minimal() +
theme(legend.position = "none")
}
# Creazione dei grafici a barre per ogni variabile categorica
bar_plots <- lapply(names(categorical_vars), function(var) plot_bar(categorical_vars, var))
# Visualizzazione dei grafici a barre
wrap_plots(bar_plots, ncol = 2)
# Tabelle di frequenza
for (var in names(categorical_vars)) {
cat("\nTabella di frequenza per", var, ":\n")
print(table(categorical_vars[[var]]))
cat("Percentuali:\n")
print(round(prop.table(table(categorical_vars[[var]])) * 100, 2))
cat("\n")
}
##
## Tabella di frequenza per Fumatrice :
##
## No Si
## 2396 104
## Percentuali:
##
## No Si
## 95.84 4.16
##
##
## Tabella di frequenza per Tipo_parto :
##
## Ces Nat
## 728 1772
## Percentuali:
##
## Ces Nat
## 29.12 70.88
##
##
## Tabella di frequenza per Ospedale :
##
## osp1 osp2 osp3
## 816 849 835
## Percentuali:
##
## osp1 osp2 osp3
## 32.64 33.96 33.40
##
##
## Tabella di frequenza per Sesso :
##
## F M
## 1256 1244
## Percentuali:
##
## F M
## 50.24 49.76
# Matrice di correlazione per le variabili numeriche
cor_matrix <- cor(numeric_vars)
corrplot(cor_matrix, method = "circle", type = "upper",
tl.col = "black", tl.srt = 45)
# Scatter plot per le relazioni principali con il Peso
scatter_plots <- lapply(c("Gestazione", "Lunghezza", "Cranio"), function(var) {
ggplot(neonati, aes_string(x = var, y = "Peso")) +
geom_point(aes(color = Sesso), alpha = 0.7) +
geom_smooth(method = "lm", se = TRUE) +
labs(title = paste("Relazione tra", var, "e Peso"), x = var, y = "Peso (g)") +
theme_minimal()
})
wrap_plots(scatter_plots, ncol = 2)
# Relazione tra Peso e variabili categoriche
box_cat_plots <- lapply(c("Fumatrice", "Tipo_parto", "Ospedale", "Sesso"), function(var) {
ggplot(neonati, aes_string(x = var, y = "Peso", fill = var)) +
geom_boxplot() +
labs(title = paste("Relazione tra", var, "e Peso"), x = var, y = "Peso (g)") +
theme_minimal() +
theme(legend.position = "none")
})
wrap_plots(box_cat_plots, ncol = 2)
# Tabella di contingenza tra ospedale e tipo di parto
cont_table <- table(neonati$Ospedale, neonati$Tipo_parto)
print(cont_table)
##
## Ces Nat
## osp1 242 574
## osp2 254 595
## osp3 232 603
# Visualizzazione grafica
ggplot(neonati, aes(x = Ospedale, fill = Tipo_parto)) +
geom_bar(position = "fill") +
labs(title = "Proporzione di Tipi di Parto per Ospedale",
x = "Ospedale", y = "Proporzione") +
scale_y_continuous(labels = scales::percent) +
theme_minimal()
# Test chi-quadrato per verificare l'associazione
chi_test <- chisq.test(cont_table)
print(chi_test)
##
## Pearson's Chi-squared test
##
## data: cont_table
## X-squared = 1.0972, df = 2, p-value = 0.5778
# Post-hoc analysis con test di proporzione a coppie
pairwise.prop.test(cont_table, p.adjust.method = "bonferroni")
##
## Pairwise comparisons using Pairwise comparison of proportions
##
## data: cont_table
##
## osp1 osp2
## osp2 1 -
## osp3 1 1
##
## P value adjustment method: bonferroni
# Valori di riferimento per la popolazione italiana (esempio)
# Questi valori dovrebbero essere sostituiti con dati reali di riferimento
peso_rif <- 3300 # grammi, valore medio di riferimento
lunghezza_rif <- 50 # cm, valore medio di riferimento
# Test t per il peso
t_test_peso <- t.test(neonati$Peso, mu = peso_rif)
print(t_test_peso)
##
## One Sample t-test
##
## data: neonati$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 t per la lunghezza
t_test_lunghezza <- t.test(neonati$Lunghezza, mu = lunghezza_rif)
print(t_test_lunghezza)
##
## One Sample t-test
##
## data: neonati$Lunghezza
## t = 844.82, df = 2499, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 50
## 95 percent confidence interval:
## 493.6598 495.7242
## sample estimates:
## mean of x
## 494.692
# Visualizzazione delle distribuzioni con linee di riferimento
peso_plot <- ggplot(neonati, aes(x = Peso)) +
geom_histogram(fill = "steelblue", color = "white", bins = 30) +
geom_vline(xintercept = peso_rif, color = "red", linetype = "dashed", size = 1) +
geom_vline(xintercept = mean(neonati$Peso), color = "green", linetype = "solid", size = 1) +
labs(title = "Distribuzione del Peso con Riferimento",
x = "Peso (g)", y = "Conteggio") +
annotate("text", x = peso_rif + 150, y = 150, label = "Rif. Pop.", color = "red") +
annotate("text", x = mean(neonati$Peso) + 150, y = 180, label = "Media Camp.", color = "green") +
theme_minimal()
lunghezza_plot <- ggplot(neonati, aes(x = Lunghezza)) +
geom_histogram(fill = "steelblue", color = "white", bins = 30) +
geom_vline(xintercept = lunghezza_rif, color = "red", linetype = "dashed", size = 1) +
geom_vline(xintercept = mean(neonati$Lunghezza), color = "green", linetype = "solid", size = 1) +
labs(title = "Distribuzione della Lunghezza con Riferimento",
x = "Lunghezza (cm)", y = "Conteggio") +
annotate("text", x = lunghezza_rif + 1, y = 150, label = "Rif. Pop.", color = "red") +
annotate("text", x = mean(neonati$Lunghezza) + 1, y = 180, label = "Media Camp.", color = "green") +
theme_minimal()
peso_plot / lunghezza_plot
# Test t per confrontare il peso tra i sessi
t_test_peso_sesso <- t.test(Peso ~ Sesso, data = neonati)
print(t_test_peso_sesso)
##
## 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
# Test t per confrontare la lunghezza tra i sessi
t_test_lunghezza_sesso <- t.test(Lunghezza ~ Sesso, data = neonati)
print(t_test_lunghezza_sesso)
##
## 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:
## -11.929470 -7.876273
## sample estimates:
## mean in group F mean in group M
## 489.7643 499.6672
# Test t per confrontare il diametro cranico tra i sessi
t_test_cranio_sesso <- t.test(Cranio ~ Sesso, data = neonati)
print(t_test_cranio_sesso)
##
## 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:
## -6.089912 -3.541270
## sample estimates:
## mean in group F mean in group M
## 337.6330 342.4486
# Visualizzazione delle differenze con boxplot
anthropometric_vars <- c("Peso", "Lunghezza", "Cranio")
anthropometric_plots <- lapply(anthropometric_vars, function(var) {
ggplot(neonati, aes_string(x = "Sesso", y = var, fill = "Sesso")) +
geom_boxplot() +
labs(title = paste("Confronto di", var, "tra i Sessi"),
x = "Sesso", y = var) +
theme_minimal() +
theme(legend.position = "none")
})
wrap_plots(anthropometric_plots, ncol = 3)
# MANOVA per testare le differenze in tutte le variabili antropometriche simultaneamente
manova_result <- manova(cbind(Peso, Lunghezza, Cranio) ~ Sesso, data = neonati)
summary(manova_result)
## Df Pillai approx F num Df den Df Pr(>F)
## Sesso 1 0.05614 49.487 3 2496 < 2.2e-16 ***
## Residuals 2498
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Calcolo delle statistiche descrittive per gruppo
neonati %>%
group_by(Sesso) %>%
summarise(
Media_Peso = mean(Peso),
DS_Peso = sd(Peso),
Media_Lunghezza = mean(Lunghezza),
DS_Lunghezza = sd(Lunghezza),
Media_Cranio = mean(Cranio),
DS_Cranio = sd(Cranio)
) %>%
kbl() %>%
kable_styling(bootstrap_options = c("striped", "hover"))
| Sesso | Media_Peso | DS_Peso | Media_Lunghezza | DS_Lunghezza | Media_Cranio | DS_Cranio |
|---|---|---|---|---|---|---|
| F | 3161.132 | 526.3091 | 489.7643 | 27.53415 | 337.6330 | 16.73772 |
| M | 3408.215 | 493.8043 | 499.6672 | 24.03809 | 342.4486 | 15.74448 |
# Funzione per identificare outlier usando il metodo IQR
outliers_detector <- function(x) {
Q1 <- quantile(x, 0.25)
Q3 <- quantile(x, 0.75)
IQR <- Q3 - Q1
lower_bound <- Q1 - 1.5 * IQR
upper_bound <- Q3 + 1.5 * IQR
return(x < lower_bound | x > upper_bound)
}
# Identificazione degli outlier nella variabile Peso
outliers_peso <- outliers_detector(neonati$Peso)
cat("Numero di outlier in Peso:", sum(outliers_peso), "su", length(neonati$Peso), "osservazioni\n")
## Numero di outlier in Peso: 69 su 2500 osservazioni
# Visualizzazione con boxplot
par(mfrow = c(1, 2))
boxplot(neonati$Peso, main = "Peso - Con outlier", col = "lightblue")
boxplot(neonati$Peso[!outliers_peso], main = "Peso - Senza outlier", col = "lightgreen")
par(mfrow = c(1, 1))
# Creazione di un dataset senza outlier per confronto
neonati_no_outliers <- neonati[!outliers_peso, ]
cat("Dimensione del dataset originale:", nrow(neonati), "\n")
## Dimensione del dataset originale: 2500
cat("Dimensione del dataset senza outlier:", nrow(neonati_no_outliers), "\n")
## Dimensione del dataset senza outlier: 2431
# Confronto delle statistiche descrittive con e senza outlier
summary_comparison <- data.frame(
Statistica = c("Media", "Mediana", "Min", "Max", "SD"),
Con_Outlier = c(mean(neonati$Peso), median(neonati$Peso), min(neonati$Peso), max(neonati$Peso), sd(neonati$Peso)),
Senza_Outlier = c(mean(neonati_no_outliers$Peso), median(neonati_no_outliers$Peso), min(neonati_no_outliers$Peso), max(neonati_no_outliers$Peso), sd(neonati_no_outliers$Peso))
)
summary_comparison %>%
kbl() %>%
kable_styling(bootstrap_options = c("striped", "hover"))
| Statistica | Con_Outlier | Senza_Outlier |
|---|---|---|
| Media | 3284.0808 | 3314.9329 |
| Mediana | 3300.0000 | 3300.0000 |
| Min | 830.0000 | 2050.0000 |
| Max | 4930.0000 | 4560.0000 |
| SD | 525.0387 | 447.8165 |
# Valutare se usare il dataset originale o quello senza outlier
# Per questa analisi, useremo entrambi per confronto
set.seed(42) # Per riproducibilità
# Dataset originale
training_index <- createDataPartition(neonati$Peso, p = 0.8, list = FALSE)
training_set <- neonati[training_index, ]
test_set <- neonati[-training_index, ]
# Dataset senza outlier
training_index_no_out <- createDataPartition(neonati_no_outliers$Peso, p = 0.8, list = FALSE)
training_set_no_out <- neonati_no_outliers[training_index_no_out, ]
test_set_no_out <- neonati_no_outliers[-training_index_no_out, ]
# Dimensioni dei dataset
cat("Dimensioni del training set originale:", dim(training_set), "\n")
## Dimensioni del training set originale: 2002 10
cat("Dimensioni del test set originale:", dim(test_set), "\n")
## Dimensioni del test set originale: 498 10
cat("Dimensioni del training set senza outlier:", dim(training_set_no_out), "\n")
## Dimensioni del training set senza outlier: 1946 10
cat("Dimensioni del test set senza outlier:", dim(test_set_no_out), "\n")
## Dimensioni del test set senza outlier: 485 10
# Trasformazione logaritmica della variabile target
# Aggiungiamo la variabile log_Peso per valutare modelli con target trasformato
neonati$log_Peso <- log(neonati$Peso)
training_set$log_Peso <- log(training_set$Peso)
test_set$log_Peso <- log(test_set$Peso)
# Visualizzazione della distribuzione originale vs log-trasformata
par(mfrow = c(1, 2))
hist(neonati$Peso, main = "Distribuzione del Peso", col = "lightblue")
hist(neonati$log_Peso, main = "Distribuzione del log(Peso)", col = "lightgreen")
par(mfrow = c(1, 1))
# Modello lineare completo
full_model <- lm(Peso ~ Eta_madre + N_gravidanze + Fumatrice + Gestazione +
Lunghezza + Cranio + Tipo_parto + Ospedale + Sesso, data = training_set)
# Modello con variabile target log-trasformata
log_model <- lm(log_Peso ~ Eta_madre + N_gravidanze + Fumatrice + Gestazione +
Lunghezza + Cranio + Tipo_parto + Ospedale + Sesso, data = training_set)
# Riepilogo dei modelli
summary(full_model)
##
## Call:
## lm(formula = Peso ~ Eta_madre + N_gravidanze + Fumatrice + Gestazione +
## Lunghezza + Cranio + Tipo_parto + Ospedale + Sesso, data = training_set)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1133.45 -180.66 -14.09 165.36 1431.28
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6665.3835 152.8345 -43.612 < 2e-16 ***
## Eta_madre 0.7223 1.2566 0.575 0.56547
## N_gravidanze 10.7770 5.1610 2.088 0.03691 *
## FumatriceSi -15.7222 30.5179 -0.515 0.60648
## Gestazione 28.5429 4.1790 6.830 1.12e-11 ***
## Lunghezza 11.2931 0.3412 33.095 < 2e-16 ***
## Cranio 9.2608 0.4758 19.465 < 2e-16 ***
## Tipo_partoNat 40.9279 13.4420 3.045 0.00236 **
## Ospedaleosp2 -6.3149 14.8534 -0.425 0.67078
## Ospedaleosp3 30.4889 14.9378 2.041 0.04138 *
## SessoM 67.7361 12.3477 5.486 4.64e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 271.2 on 1991 degrees of freedom
## Multiple R-squared: 0.7399, Adjusted R-squared: 0.7386
## F-statistic: 566.3 on 10 and 1991 DF, p-value: < 2.2e-16
summary(log_model)
##
## Call:
## lm(formula = log_Peso ~ Eta_madre + N_gravidanze + Fumatrice +
## Gestazione + Lunghezza + Cranio + Tipo_parto + Ospedale +
## Sesso, data = training_set)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.39470 -0.05496 -0.00061 0.05368 0.51754
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.3826745 0.0482140 90.900 < 2e-16 ***
## Eta_madre 0.0001092 0.0003964 0.275 0.7830
## N_gravidanze 0.0037258 0.0016281 2.288 0.0222 *
## FumatriceSi -0.0028773 0.0096273 -0.299 0.7651
## Gestazione 0.0177720 0.0013183 13.481 < 2e-16 ***
## Lunghezza 0.0038709 0.0001076 35.959 < 2e-16 ***
## Cranio 0.0031353 0.0001501 20.890 < 2e-16 ***
## Tipo_partoNat 0.0110556 0.0042405 2.607 0.0092 **
## Ospedaleosp2 -0.0011251 0.0046857 -0.240 0.8103
## Ospedaleosp3 0.0096537 0.0047123 2.049 0.0406 *
## SessoM 0.0154170 0.0038953 3.958 7.83e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.08554 on 1991 degrees of freedom
## Multiple R-squared: 0.7909, Adjusted R-squared: 0.7898
## F-statistic: 752.9 on 10 and 1991 DF, p-value: < 2.2e-16
# Analisi della varianza
anova(full_model)
## Analysis of Variance Table
##
## Response: Peso
## Df Sum Sq Mean Sq F value Pr(>F)
## Eta_madre 1 152531 152531 2.0746 0.149924
## N_gravidanze 1 2807 2807 0.0382 0.845110
## Fumatrice 1 75403 75403 1.0256 0.311324
## Gestazione 1 205947440 205947440 2801.1549 < 2.2e-16 ***
## Lunghezza 1 178006214 178006214 2421.1176 < 2.2e-16 ***
## Cranio 1 28732047 28732047 390.7935 < 2.2e-16 ***
## Tipo_parto 1 703815 703815 9.5728 0.002002 **
## Ospedale 2 539355 269678 3.6680 0.025701 *
## Sesso 1 2212529 2212529 30.0933 4.642e-08 ***
## Residuals 1991 146382965 73522
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Controllo della multicollinearità
vif_values <- vif(full_model)
print(vif_values)
## GVIF Df GVIF^(1/(2*Df))
## Eta_madre 1.193733 1 1.092581
## N_gravidanze 1.189832 1 1.090794
## Fumatrice 1.007809 1 1.003897
## Gestazione 1.739855 1 1.319036
## Lunghezza 2.213195 1 1.487681
## Cranio 1.694284 1 1.301647
## Tipo_parto 1.003042 1 1.001520
## Ospedale 1.005440 2 1.001357
## Sesso 1.037896 1 1.018772
# Grafici diagnostici per il modello originale
par(mfrow = c(2, 2))
plot(full_model)
par(mfrow = c(1, 1))
# Grafici diagnostici per il modello con log-trasformazione
par(mfrow = c(2, 2))
plot(log_model)
par(mfrow = c(1, 1))
# Test di normalità dei residui per entrambi i modelli
shapiro_test_orig <- shapiro.test(residuals(full_model))
shapiro_test_log <- shapiro.test(residuals(log_model))
cat("Test di Shapiro-Wilk per normalità dei residui (modello originale):\n")
## Test di Shapiro-Wilk per normalità dei residui (modello originale):
print(shapiro_test_orig)
##
## Shapiro-Wilk normality test
##
## data: residuals(full_model)
## W = 0.98728, p-value = 2.512e-12
cat("\nTest di Shapiro-Wilk per normalità dei residui (modello log-trasformato):\n")
##
## Test di Shapiro-Wilk per normalità dei residui (modello log-trasformato):
print(shapiro_test_log)
##
## Shapiro-Wilk normality test
##
## data: residuals(log_model)
## W = 0.98773, p-value = 4.756e-12
# Test di omoschedasticità per entrambi i modelli
bp_test_orig <- bptest(full_model)
bp_test_log <- bptest(log_model)
cat("Test di Breusch-Pagan per omoschedasticità (modello originale):\n")
## Test di Breusch-Pagan per omoschedasticità (modello originale):
print(bp_test_orig)
##
## studentized Breusch-Pagan test
##
## data: full_model
## BP = 14.766, df = 10, p-value = 0.1408
cat("\nTest di Breusch-Pagan per omoschedasticità (modello log-trasformato):\n")
##
## Test di Breusch-Pagan per omoschedasticità (modello log-trasformato):
print(bp_test_log)
##
## studentized Breusch-Pagan test
##
## data: log_model
## BP = 81.463, df = 10, p-value = 2.592e-13
# Selezione step-wise basata su AIC per entrambi i modelli
step_model <- stepAIC(full_model, direction = "both", trace = FALSE)
step_log_model <- stepAIC(log_model, direction = "both", trace = FALSE)
# Confronto tra modelli
anova(step_model, full_model)
## Analysis of Variance Table
##
## Model 1: Peso ~ N_gravidanze + Gestazione + Lunghezza + Cranio + Tipo_parto +
## Ospedale + Sesso
## Model 2: Peso ~ Eta_madre + N_gravidanze + Fumatrice + Gestazione + Lunghezza +
## Cranio + Tipo_parto + Ospedale + Sesso
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 1993 146426260
## 2 1991 146382965 2 43295 0.2944 0.745
anova(step_log_model, log_model)
## Analysis of Variance Table
##
## Model 1: log_Peso ~ N_gravidanze + Gestazione + Lunghezza + Cranio + Tipo_parto +
## Ospedale + Sesso
## Model 2: log_Peso ~ Eta_madre + N_gravidanze + Fumatrice + Gestazione +
## Lunghezza + Cranio + Tipo_parto + Ospedale + Sesso
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 1993 14.569
## 2 1991 14.568 2 0.0011946 0.0816 0.9216
# Riepilogo dei modelli selezionati
summary(step_model)
##
## Call:
## lm(formula = Peso ~ N_gravidanze + Gestazione + Lunghezza + Cranio +
## Tipo_parto + Ospedale + Sesso, data = training_set)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1124.49 -181.70 -14.97 165.66 1434.18
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6641.2699 147.0726 -45.156 < 2e-16 ***
## N_gravidanze 11.7379 4.7818 2.455 0.0142 *
## Gestazione 28.1504 4.1444 6.792 1.45e-11 ***
## Lunghezza 11.3023 0.3408 33.160 < 2e-16 ***
## Cranio 9.2761 0.4751 19.525 < 2e-16 ***
## Tipo_partoNat 40.8410 13.4367 3.040 0.0024 **
## Ospedaleosp2 -6.2677 14.8480 -0.422 0.6730
## Ospedaleosp3 30.9582 14.9199 2.075 0.0381 *
## SessoM 67.8020 12.3393 5.495 4.41e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 271.1 on 1993 degrees of freedom
## Multiple R-squared: 0.7398, Adjusted R-squared: 0.7388
## F-statistic: 708.3 on 8 and 1993 DF, p-value: < 2.2e-16
summary(step_log_model)
##
## Call:
## lm(formula = log_Peso ~ N_gravidanze + Gestazione + Lunghezza +
## Cranio + Tipo_parto + Ospedale + Sesso, data = training_set)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.39592 -0.05488 -0.00047 0.05378 0.51800
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.3863305 0.0463914 94.551 < 2e-16 ***
## N_gravidanze 0.0038666 0.0015083 2.563 0.01044 *
## Gestazione 0.0177086 0.0013073 13.546 < 2e-16 ***
## Lunghezza 0.0038725 0.0001075 36.019 < 2e-16 ***
## Cranio 0.0031377 0.0001499 20.938 < 2e-16 ***
## Tipo_partoNat 0.0110415 0.0042384 2.605 0.00925 **
## Ospedaleosp2 -0.0011172 0.0046835 -0.239 0.81149
## Ospedaleosp3 0.0097307 0.0047062 2.068 0.03880 *
## SessoM 0.0154242 0.0038922 3.963 7.67e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.0855 on 1993 degrees of freedom
## Multiple R-squared: 0.7908, Adjusted R-squared: 0.79
## F-statistic: 942 on 8 and 1993 DF, p-value: < 2.2e-16
# Confronto tra tutti i modelli in base all'R² aggiustato e AIC
model_comparison <- data.frame(
Modello = c("Completo", "Step-wise", "Log-Completo", "Log-Step-wise"),
R2_adj = c(summary(full_model)$adj.r.squared,
summary(step_model)$adj.r.squared,
summary(log_model)$adj.r.squared,
summary(step_log_model)$adj.r.squared),
AIC = c(AIC(full_model),
AIC(step_model),
AIC(log_model),
AIC(step_log_model))
)
model_comparison %>%
kbl() %>%
kable_styling(bootstrap_options = c("striped", "hover"))
| Modello | R2_adj | AIC |
|---|---|---|
| Completo | 0.7385751 | 28127.499 |
| Step-wise | 0.7387602 | 28124.091 |
| Log-Completo | 0.7898152 | -4150.590 |
| Log-Step-wise | 0.7900089 | -4154.426 |
# Configurazione della cross-validazione a k-fold
set.seed(123)
train_control <- trainControl(method = "cv", number = 10)
# Addestramento del modello con cross-validazione
cv_model <- train(
Peso ~ N_gravidanze + Gestazione + Lunghezza + Cranio + Tipo_parto + Ospedale + Sesso,
data = neonati,
method = "lm",
trControl = train_control
)
# Risultati della cross-validazione
print(cv_model)
## Linear Regression
##
## 2500 samples
## 7 predictor
##
## No pre-processing
## Resampling: Cross-Validated (10 fold)
## Summary of sample sizes: 2250, 2249, 2251, 2250, 2250, 2250, ...
## Resampling results:
##
## RMSE Rsquared MAE
## 274.2683 0.7248875 210.4588
##
## Tuning parameter 'intercept' was held constant at a value of TRUE
cat("\nPerformance media su 10-fold CV:",
paste("RMSE =", round(cv_model$results$RMSE, 2), "g,",
"R² =", round(cv_model$results$Rsquared, 3)))
##
## Performance media su 10-fold CV: RMSE = 274.27 g, R² = 0.725
# Cross-validazione per il modello log-trasformato
cv_log_model <- train(
log_Peso ~ N_gravidanze + Gestazione + Lunghezza + Cranio + Tipo_parto + Ospedale + Sesso,
data = neonati,
method = "lm",
trControl = train_control
)
print(cv_log_model)
## Linear Regression
##
## 2500 samples
## 7 predictor
##
## No pre-processing
## Resampling: Cross-Validated (10 fold)
## Summary of sample sizes: 2250, 2250, 2251, 2249, 2250, 2251, ...
## Resampling results:
##
## RMSE Rsquared MAE
## 0.08648719 0.7727106 0.06617148
##
## Tuning parameter 'intercept' was held constant at a value of TRUE
# Importanza delle variabili nel modello
varImp_cv <- varImp(cv_model)
plot(varImp_cv, top = 10, main = "Importanza delle Variabili nel Modello")
# Creare un grafico personalizzato dell'importanza delle variabili
var_importance <- as.data.frame(varImp_cv$importance)
var_importance$Variable <- rownames(var_importance)
var_importance <- var_importance[order(var_importance$Overall, decreasing = TRUE), ]
ggplot(var_importance, aes(x = reorder(Variable, Overall), y = Overall)) +
geom_bar(stat = "identity", fill = "steelblue") +
coord_flip() +
labs(title = "Importanza delle Variabili nel Modello",
x = "Variabile", y = "Importanza") +
theme_minimal()
# Addestramento di un modello Random Forest
set.seed(123)
rf_model <- train(
Peso ~ N_gravidanze + Gestazione + Lunghezza + Cranio + Tipo_parto + Ospedale + Sesso,
data = neonati,
method = "rf",
trControl = train_control,
ntree = 100
)
# Confronto tra modelli
models_list <- list(
LinearModel = cv_model,
RandomForest = rf_model
)
results <- resamples(models_list)
summary(results)
##
## Call:
## summary.resamples(object = results)
##
## Models: LinearModel, RandomForest
## Number of resamples: 10
##
## MAE
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## LinearModel 193.4207 204.9437 210.1666 210.4588 215.9928 227.5142 0
## RandomForest 196.2256 211.4659 214.1994 216.6700 226.4061 231.3790 0
##
## RMSE
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## LinearModel 244.6356 267.8105 269.9106 274.2683 278.3420 323.8802 0
## RandomForest 249.7530 270.3874 275.8728 278.1217 292.1085 296.0758 0
##
## Rsquared
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## LinearModel 0.6102050 0.7072107 0.7330453 0.7248875 0.7497451 0.8099513 0
## RandomForest 0.6754643 0.6807074 0.7199982 0.7235355 0.7521509 0.8050224 0
# Visualizzazione del confronto
bwplot(results, main = "Confronto tra Modelli")
# Predizioni sul test set per entrambi i modelli
lm_predictions <- predict(step_model, newdata = test_set)
rf_predictions <- predict(rf_model, newdata = test_set)
# Metriche di valutazione
lm_rmse <- sqrt(mean((test_set$Peso - lm_predictions)^2))
rf_rmse <- sqrt(mean((test_set$Peso - rf_predictions)^2))
lm_r2 <- cor(test_set$Peso, lm_predictions)^2
rf_r2 <- cor(test_set$Peso, rf_predictions)^2
# Riepilogo delle metriche
metrics_comparison <- data.frame(
Modello = c("Regressione Lineare", "Random Forest"),
RMSE = c(lm_rmse, rf_rmse),
R2 = c(lm_r2, rf_r2)
)
metrics_comparison %>%
kbl() %>%
kable_styling(bootstrap_options = c("striped", "hover"))
| Modello | RMSE | R2 |
|---|---|---|
| Regressione Lineare | 288.9667 | 0.6710005 |
| Random Forest | 198.2651 | 0.8632661 |
# Grafico delle predizioni per entrambi i modelli
test_set$LM_Predictions <- lm_predictions
test_set$RF_Predictions <- rf_predictions
lm_plot <- ggplot(test_set, aes(x = Peso, y = LM_Predictions)) +
geom_point(alpha = 0.7) +
geom_abline(intercept = 0, slope = 1, color = "red", linetype = "dashed") +
labs(title = "Regressione Lineare: Predetti vs Reali",
x = "Peso Reale (g)", y = "Peso Predetto (g)") +
theme_minimal()
rf_plot <- ggplot(test_set, aes(x = Peso, y = RF_Predictions)) +
geom_point(alpha = 0.7) +
geom_abline(intercept = 0, slope = 1, color = "red", linetype = "dashed") +
labs(title = "Random Forest: Predetti vs Reali",
x = "Peso Reale (g)", y = "Peso Predetto (g)") +
theme_minimal()
lm_plot + rf_plot
# Modello con interazioni di interesse
interaction_model <- lm(Peso ~ Gestazione + Fumatrice + Sesso + Gestazione:Fumatrice + Gestazione:Sesso,
data = training_set)
summary(interaction_model)
##
## Call:
## lm(formula = Peso ~ Gestazione + Fumatrice + Sesso + Gestazione:Fumatrice +
## Gestazione:Sesso, data = training_set)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1529.26 -280.29 -19.14 270.13 1950.99
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -3102.7270 250.4777 -12.387 <2e-16 ***
## Gestazione 162.0497 6.4593 25.088 <2e-16 ***
## FumatriceSi 1423.0729 1243.4824 1.144 0.253
## SessoM 125.6626 389.5974 0.323 0.747
## Gestazione:FumatriceSi -38.4954 31.6533 -1.216 0.224
## Gestazione:SessoM 0.8126 9.9775 0.081 0.935
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 417 on 1996 degrees of freedom
## Multiple R-squared: 0.3834, Adjusted R-squared: 0.3818
## F-statistic: 248.2 on 5 and 1996 DF, p-value: < 2.2e-16
# Visualizzazione degli effetti di interazione
interaction.plot(x.factor = cut(neonati$Gestazione, breaks = 5),
trace.factor = neonati$Sesso,
response = neonati$Peso,
xlab = "Settimane di Gestazione",
ylab = "Peso Medio (g)",
trace.label = "Sesso",
col = c("blue", "red"),
lwd = 2)
interaction.plot(x.factor = cut(neonati$Gestazione, breaks = 5),
trace.factor = neonati$Fumatrice,
response = neonati$Peso,
xlab = "Settimane di Gestazione",
ylab = "Peso Medio (g)",
trace.label = "Fumatrice",
col = c("green", "orange"),
lwd = 2)
# Visualizzazione migliorata delle interazioni con ggplot2
ggplot(neonati, aes(x = Gestazione, y = Peso, color = Sesso)) +
geom_point(alpha = 0.3) +
geom_smooth(method = "lm", se = TRUE) +
labs(title = "Interazione tra Gestazione e Sesso",
x = "Settimane di Gestazione", y = "Peso (g)") +
theme_minimal()
ggplot(neonati, aes(x = Gestazione, y = Peso, color = Fumatrice)) +
geom_point(alpha = 0.3) +
geom_smooth(method = "lm", se = TRUE) +
labs(title = "Interazione tra Gestazione e Abitudine al Fumo",
x = "Settimane di Gestazione", y = "Peso (g)") +
theme_minimal()
# Analisi per ospedale
ggplot(neonati, aes(x = Ospedale, y = Peso, fill = Ospedale)) +
geom_boxplot() +
labs(title = "Distribuzione del Peso per Ospedale",
x = "Ospedale", y = "Peso (g)") +
theme_minimal() +
theme(legend.position = "none")
# ANOVA per differenze tra ospedali
hospital_anova <- aov(Peso ~ Ospedale, data = neonati)
summary(hospital_anova)
## Df Sum Sq Mean Sq F value Pr(>F)
## Ospedale 2 936237 468118 1.699 0.183
## Residuals 2497 687952305 275512
TukeyHSD(hospital_anova)
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = Peso ~ Ospedale, data = neonati)
##
## $Ospedale
## diff lwr upr p adj
## osp2-osp1 0.2169897 -60.12780 60.56178 0.9999608
## osp3-osp1 41.1412543 -19.45096 101.73347 0.2491220
## osp3-osp2 40.9242645 -19.06942 100.91795 0.2459336
# Analisi per fumatori/non fumatori
ggplot(neonati, aes(x = Fumatrice, y = Peso, fill = Fumatrice)) +
geom_boxplot() +
labs(title = "Distribuzione del Peso per Abitudine al Fumo",
x = "Fumatrice", y = "Peso (g)") +
theme_minimal() +
theme(legend.position = "none")
# Test t per differenze tra fumatori/non fumatori
t.test(Peso ~ Fumatrice, data = neonati)
##
## Welch Two Sample t-test
##
## data: Peso by Fumatrice
## t = 1.034, df = 114.1, p-value = 0.3033
## alternative hypothesis: true difference in means between group No and group Si is not equal to 0
## 95 percent confidence interval:
## -45.61354 145.22674
## sample estimates:
## mean in group No mean in group Si
## 3286.153 3236.346
# Modelli separati per sottogruppi
# Modello per neonati maschi
model_M <- lm(Peso ~ Gestazione + Lunghezza + Cranio, data = subset(neonati, Sesso == "M"))
summary(model_M)
##
## Call:
## lm(formula = Peso ~ Gestazione + Lunghezza + Cranio, data = subset(neonati,
## Sesso == "M"))
##
## Residuals:
## Min 1Q Median 3Q Max
## -1150.58 -178.31 -10.95 168.56 1396.31
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6799.3898 204.6728 -33.221 < 2e-16 ***
## Gestazione 31.3569 5.5886 5.611 2.48e-08 ***
## Lunghezza 10.7254 0.4461 24.040 < 2e-16 ***
## Cranio 10.5661 0.6056 17.448 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 269.3 on 1240 degrees of freedom
## Multiple R-squared: 0.7034, Adjusted R-squared: 0.7026
## F-statistic: 980 on 3 and 1240 DF, p-value: < 2.2e-16
# Modello per neonati femmine
model_F <- lm(Peso ~ Gestazione + Lunghezza + Cranio, data = subset(neonati, Sesso == "F"))
summary(model_F)
##
## Call:
## lm(formula = Peso ~ Gestazione + Lunghezza + Cranio, data = subset(neonati,
## Sesso == "F"))
##
## Residuals:
## Min 1Q Median 3Q Max
## -1020.64 -190.25 -25.16 157.09 2556.91
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6485.0132 183.6378 -35.314 < 2e-16 ***
## Gestazione 31.6086 5.1692 6.115 1.29e-09 ***
## Lunghezza 9.8102 0.4082 24.032 < 2e-16 ***
## Cranio 10.7133 0.5961 17.972 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 280.5 on 1252 degrees of freedom
## Multiple R-squared: 0.7167, Adjusted R-squared: 0.716
## F-statistic: 1056 on 3 and 1252 DF, p-value: < 2.2e-16
# Confronto tra coefficienti dei due modelli
coefficients_comparison <- data.frame(
Variabile = c("Intercetta", "Gestazione", "Lunghezza", "Cranio"),
Maschi = c(coef(model_M)[1], coef(model_M)[2], coef(model_M)[3], coef(model_M)[4]),
Femmine = c(coef(model_F)[1], coef(model_F)[2], coef(model_F)[3], coef(model_F)[4])
)
coefficients_comparison %>%
kbl() %>%
kable_styling(bootstrap_options = c("striped", "hover"))
| Variabile | Maschi | Femmine | |
|---|---|---|---|
| (Intercept) | Intercetta | -6799.38979 | -6485.013182 |
| Gestazione | Gestazione | 31.35687 | 31.608599 |
| Lunghezza | Lunghezza | 10.72541 | 9.810191 |
| Cranio | Cranio | 10.56609 | 10.713288 |
La nostra analisi ha identificato diversi fattori significativi che influenzano il peso alla nascita dei neonati:
Il modello di regressione lineare ottimale (dopo selezione stepwise) ha evidenziato le seguenti variabili come significative:
Il modello ha mostrato una buona capacità predittiva con un R² aggiustato di 0.739, indicando che circa il 73.9% della variabilità nel peso neonatale può essere spiegata dalle variabili incluse.
Il modello Random Forest ha mostrato performance significativamente migliori rispetto alla regressione lineare, suggerendo relazioni non lineari tra le variabili predittive e il peso alla nascita.
Confronto delle predizioni dei modelli sul test set
Differenze tra ospedali nei parti cesarei: Non sono state rilevate differenze statisticamente significative nella frequenza dei parti cesarei tra i tre ospedali (χ² = 1.097, p = 0.578).
Confronto con valori di riferimento:
Differenze tra sessi nelle misure antropometriche:
Differenze antropometriche tra neonati maschi e femmine
I risultati di questa analisi hanno diverse implicazioni per la pratica clinica:
Identificazione di neonati a rischio: Il modello sviluppato può aiutare a identificare precocemente i neonati a rischio di basso peso, consentendo un intervento tempestivo.
Gestione personalizzata delle gravidanze: Le variabili identificate come più influenti (gestazione, lunghezza, circonferenza cranica) possono essere monitorate con maggiore attenzione durante la gravidanza per valutare il rischio di peso inadeguato alla nascita.
Pianificazione delle risorse ospedaliere: La capacità di prevedere con maggiore precisione il peso alla nascita può aiutare nell’allocazione delle risorse neonatali.
Approccio differenziato per sesso: Date le differenze significative tra neonati maschi e femmine, potrebbe essere utile considerare il sesso nelle valutazioni cliniche prenatali.
Implementazione di modelli avanzati: Il modello Random Forest ha mostrato performance superiori, suggerendo l’utilità di approcci di machine learning nella pratica clinica per migliorare la precisione predittiva.
Nonostante i risultati promettenti, questo studio presenta alcune limitazioni:
Rappresentatività del campione: I dati provengono da soli tre ospedali, limitando potenzialmente la generalizzabilità dei risultati.
Variabili non considerate: Fattori potenzialmente rilevanti come la nutrizione materna, lo status socioeconomico e complicazioni della gravidanza non sono stati inclusi nel modello.
Dimensione temporale: Lo studio non considera l’evoluzione temporale delle gravidanze, limitandosi a misurazioni statiche.
Effetto del fumo: Sebbene le madri fumatrici tendano ad avere neonati con peso inferiore, questa associazione non ha raggiunto la significatività statistica nel nostro campione, probabilmente a causa del numero limitato di fumatrici (4.16%).
Interpretabilità del modello Random Forest: Nonostante le performance superiori, i modelli di machine learning sono meno interpretabili rispetto ai modelli lineari, limitando potenzialmente la loro applicabilità clinica.
Importanza delle variabili nel modello Random Forest
Per migliorare ulteriormente questo lavoro, suggeriamo le seguenti direzioni di ricerca:
Espansione del dataset: Includere dati da più ospedali e regioni geografiche per migliorare la generalizzabilità.
Variabili aggiuntive: Integrare fattori materni come BMI pre-gravidanza, aumento di peso durante la gravidanza, nutrizione e comorbidità.
Validazione esterna: Testare il modello su dataset indipendenti per valutarne la robustezza.
Modelli longitudinali: Sviluppare modelli che considerino l’evoluzione temporale dei parametri durante la gravidanza.
Sviluppo di uno strumento clinico: Implementare il modello predittivo in un’applicazione di facile utilizzo per i clinici.
Analisi di altri outcome neonatali: Estendere l’approccio predittivo ad altri parametri di salute neonatale oltre al peso alla nascita.
In conclusione, questo studio fornisce un contributo significativo alla comprensione dei fattori che influenzano il peso neonatale e offre uno strumento predittivo con potenziali applicazioni nella pratica clinica. L’integrazione di approcci di machine learning con l’esperienza clinica potrebbe portare a strategie più efficaci per la gestione delle gravidanze e il miglioramento degli outcome neonatali.