1 Caricamento dati

dati <- read.csv("neonati.csv", sep = ",", stringsAsFactors = FALSE)

# Sistemo tipi
for(v in c("Sesso","Tipo.parto","Ospedale")){
  if(v %in% names(dati)) dati[[v]] <- factor(dati[[v]])
}

if("Fumatrici" %in% names(dati)){
  dati$Fumatrici <- factor(dati$Fumatrici, levels=c(0,1), labels=c("No","Si"))  
}

if("N.gravidanze" %in% names(dati)){
  dati$N.gravidanze <- suppressWarnings(as.numeric(dati$N.gravidanze))
}

n <- nrow(dati)

kable(data.frame(Osservazioni=n, Variabili=ncol(dati)),
      caption="Dimensioni del dataset")
Dimensioni del dataset
Osservazioni Variabili
2500 10
struttura <- data.frame(
  Variabile = names(dati),
  Classe = sapply(dati, class),
  row.names = NULL
)

kable(struttura, caption = "Struttura delle variabili")
Struttura delle variabili
Variabile Classe
Anni.madre integer
N.gravidanze numeric
Fumatrici factor
Gestazione integer
Peso integer
Lunghezza integer
Cranio integer
Tipo.parto factor
Ospedale factor
Sesso factor

2 Analisi descrittiva Peso

peso_stats <- data.frame(
  Skewness = skewness(dati$Peso),
  Kurtosis_excess = kurtosis(dati$Peso)-3,
  Shapiro_W = shapiro.test(dati$Peso)$statistic,
  Shapiro_p = shapiro.test(dati$Peso)$p.value
)
kable(as.data.frame(lapply(peso_stats, rd)),
      caption="Indici forma e normalità Peso")
Indici forma e normalità Peso
Skewness Kurtosis_excess Shapiro_W Shapiro_p
-0.65 2.03 0.97 0
plot(density(dati$Peso),
     main="Densità del Peso", xlab="Peso (g)")

# Individuazione outlier su Peso (regola IQR)
Q1 <- quantile(dati$Peso, 0.25, na.rm=TRUE)
Q3 <- quantile(dati$Peso, 0.75, na.rm=TRUE)
IQR_val <- IQR(dati$Peso, na.rm=TRUE)

lower <- Q1 - 1.5 * IQR_val
upper <- Q3 + 1.5 * IQR_val

outliers_peso <- which(dati$Peso < lower | dati$Peso > upper)

kable(data.frame(
  Numero_outlier = length(outliers_peso),
  Soglia_inferiore = round(lower,1),
  Soglia_superiore = round(upper,1)
), caption="Outlier del Peso (regola IQR)")
Outlier del Peso (regola IQR)
Numero_outlier Soglia_inferiore Soglia_superiore
25% 69 2045 4565

L’analisi descrittiva del peso alla nascita mostra una distribuzione complessivamente regolare, ma con una moderata asimmetria negativa. I valori di skewness e kurtosis suggeriscono infatti una distribuzione leggermente asimmetrica e più concentrata nelle regioni centrali, con code più pesanti rispetto a una distribuzione normale. Il test di Shapiro-Wilk risulta significativo, ma viene riportato a scopo descrittivo poiché, data l’elevata numerosità campionaria, anche scostamenti contenuti dalla normalità possono risultare statisticamente significativi. L’individuazione degli outlier tramite la regola dell’IQR evidenzia la presenza di alcune osservazioni estreme, che possono essere associate a neonati con peso particolarmente basso o elevato rispetto alla media.

3 Test media campione vs popolazione

# Valori di riferimento clinico
mu_peso <- 3300
mu_lung <- 500

t_peso <- t.test(dati$Peso, mu = mu_peso)
t_lung <- t.test(dati$Lunghezza, mu = mu_lung)

tab_test <- data.frame(
  Variabile = c("Peso", "Lunghezza"),
  Mu_pop = c(mu_peso, mu_lung),
  Media_camp = c(mean(dati$Peso, na.rm = TRUE),
                 mean(dati$Lunghezza, na.rm = TRUE)),
  t = c(unname(t_peso$statistic),
        unname(t_lung$statistic)),
  p_value = c(t_peso$p.value,
              t_lung$p.value)
)

kable(as.data.frame(lapply(tab_test, rd)),
      caption = "Test t a un campione")
Test t a un campione
Variabile Mu_pop Media_camp t p_value
Peso 3300 3284.08 -1.52 0.13
Lunghezza 500 494.69 -10.08 0.00

Nota: 3300 g e 500 mm sono valori medi riportati in letteratura pediatrica e utilizzati come riferimento per il test a un campione.

Il test t a un campione è stato utilizzato per verificare se le medie osservate nel campione differiscono dai valori medi riportati in letteratura.

I risultati mostrano che la media del peso alla nascita non differisce significativamente dal valore di riferimento di 3300 g (p = 0.13), suggerendo che il campione risulta coerente con la popolazione di riferimento.

Al contrario, la lunghezza media del campione risulta significativamente inferiore al valore di riferimento di 500 mm (p < 0.001), indicando una differenza statisticamente significativa rispetto al valore riportato in letteratura.

4 Regressione semplice Peso ~ Lunghezza

mod_lin <- lm(Peso ~ Lunghezza, data=dati)

tab_lin <- as.data.frame(summary(mod_lin)$coefficients)
tab_lin$Termine <- rownames(tab_lin)
rownames(tab_lin) <- NULL
tab_lin <- tab_lin[,c("Termine","Estimate","Std. Error","t value","Pr(>|t|)")]
kable(as.data.frame(lapply(tab_lin, rd)),
      caption="Regressione semplice")
Regressione semplice
Termine Estimate Std..Error t.value Pr…t..
(Intercept) -4571.82 119.68 -38.20 0
Lunghezza 15.88 0.24 65.73 0
kable(data.frame(R2=round(summary(mod_lin)$r.squared,2)),
      caption="R²")
R2
0.63

La regressione semplice analizza la relazione tra lunghezza del neonato e peso alla nascita. La lunghezza è un predittore significativo del peso, R^2 = 0.63

5 Regressione multipla principale

mod1 <- lm(Peso ~ Lunghezza + Cranio + Gestazione, data=dati)

tab_mod1 <- as.data.frame(summary(mod1)$coefficients)
tab_mod1$Termine <- rownames(tab_mod1)
rownames(tab_mod1) <- NULL
tab_mod1 <- tab_mod1[,c("Termine","Estimate","Std. Error","t value","Pr(>|t|)")]
kable(as.data.frame(lapply(tab_mod1, rd)),
      caption="Regressione multipla")
Regressione multipla
Termine Estimate Std..Error t.value Pr…t..
(Intercept) -6777.12 135.64 -49.96 0
Lunghezza 10.43 0.30 34.52 0
Cranio 10.79 0.43 25.19 0
Gestazione 31.69 3.82 8.29 0
kable(data.frame(
  R2=round(summary(mod1)$r.squared,2),
  Adj_R2=round(summary(mod1)$adj.r.squared,2)),
  caption="R² e R² aggiustato")
R² e R² aggiustato
R2 Adj_R2
0.72 0.72

Il coefficiente di determinazione R² indica che il modello spiega circa il 72% della variabilità osservata nel peso neonatale. Lunghezza, diametro del cranio e durata della gestazione, risultano tra i predittori più rilevanti del peso alla nascita.

5.1 Modello completo (tutte le variabili) e confronto con mod1

mod_full <- lm(Peso ~ Anni.madre + N.gravidanze + Fumatrici +
                 Gestazione + Lunghezza + Cranio +
                 Tipo.parto + Ospedale + Sesso,
               data = dati)

# Confronto modelli ( modello clinico base vs completo)

kable(data.frame(
  Modello = c("mod1 (clinico base)",
              "mod_full (tutte le variabili)"),
  AIC = round(c(AIC(mod1), AIC(mod_full)), 1),
  BIC = round(c(BIC(mod1), BIC(mod_full)), 1),
  R2  = round(c(summary(mod1)$r.squared,
                summary(mod_full)$r.squared), 2),
  Adj_R2 = round(c(summary(mod1)$adj.r.squared,
                   summary(mod_full)$adj.r.squared), 2)
), caption = "Confronto: modello base vs modello completo")
Confronto: modello base vs modello completo
Modello AIC BIC R2 Adj_R2
mod1 (clinico base) 35233.0 35262.1 0.72 0.72
mod_full (tutte le variabili) 35171.9 35241.8 0.73 0.73

Il confronto tra il modello clinico di base e il modello completo mostra valori inferiori di AIC e BIC per il modello completo, indicando un miglior adattamento ai dati. Anche R^2 aumenta leggermente, ma il miglioramento complessivo resta contenuto, suggerendo che le principali informazioni predittive sono già catturate dal modello base.

6 Multicollinearità

v <- car::vif(mod_full)


if (is.matrix(v)) {
  vif_tab <- data.frame(
    Variabile = rownames(v),
    GVIF = round(v[, "GVIF"], 2),
    Df = v[, "Df"],
    GVIF_adj = round(v[, "GVIF^(1/(2*Df))"], 2),
    row.names = NULL
  )
  kable(vif_tab, caption = "Multicollinearità (GVIF) - modello completo")
  
} else {
  vif_tab <- data.frame(
    Variabile = names(v),
    VIF = round(as.numeric(v), 2)
  )
  kable(vif_tab, caption = "Multicollinearità (VIF) - modello completo")
}
Multicollinearità (GVIF) - modello completo
Variabile GVIF Df GVIF_adj
Anni.madre 1.19 1 1.09
N.gravidanze 1.19 1 1.09
Fumatrici 1.01 1 1.00
Gestazione 1.70 1 1.30
Lunghezza 2.09 1 1.44
Cranio 1.63 1 1.28
Tipo.parto 1.00 1 1.00
Ospedale 1.00 2 1.00
Sesso 1.04 1 1.02

I valori ottenuti per i VIF risultano tutti molto vicini a 1 ed inferiori alle soglie critiche comunemente utilizzate (VIF < 5). Il valore più elevato si osserva per la variabile lunghezza (GVIF_adj ≈ 1.44), ma rimane comunque molto basso. Pertanto non emergono problemi rilevanti di multicollinearità tra le variabili esplicative e il modello può essere considerato stabile dal punto di vista delle stime dei coefficienti.

7 Selezione del modello

mod_step <- MASS::stepAIC(mod_full, direction="both", trace=FALSE)

kable(data.frame(
  Modello=c("mod_full","mod_step (AIC)"),
  AIC=round(c(AIC(mod_full),AIC(mod_step)),1),
  BIC=round(c(BIC(mod_full),BIC(mod_step)),1),
  R2=round(c(summary(mod_full)$r.squared,
             summary(mod_step)$r.squared),2)
), caption="Selezione modello tramite AIC")
Selezione modello tramite AIC
Modello AIC BIC R2
mod_full 35171.9 35241.8 0.73
mod_step (AIC) 35169.8 35228.0 0.73

7.1 R² del modello selezionato

mod_final <- mod_step

kable(data.frame(
  R2 = round(summary(mod_final)$r.squared, 2),
  Adj_R2 = round(summary(mod_final)$adj.r.squared, 2)
), caption = "R² e R² aggiustato - modello selezionato (mod_final)")
R² e R² aggiustato - modello selezionato (mod_final)
R2 Adj_R2
0.73 0.73

7.2 Diagnostica sul modello selezionato (mod_final)

mod_final <- mod_step

RMSE_final <- sqrt(mean(residuals(mod_final)^2, na.rm = TRUE))
kable(data.frame(RMSE = round(RMSE_final, 2)),
      caption = "RMSE (training) - modello selezionato (mod_final)")
RMSE (training) - modello selezionato (mod_final)
RMSE
273.42
op <- par(mfrow=c(2,2))
plot(mod_final)

par(op)

tab_diag_final <- data.frame(
  Test = c("Shapiro","Breusch-Pagan","Durbin-Watson"),
  Stat = c(shapiro.test(residuals(mod_final))$statistic,
           bptest(mod_final)$statistic,
           dwtest(mod_final)$statistic),
  p_value = c(shapiro.test(residuals(mod_final))$p.value,
              bptest(mod_final)$p.value,
              dwtest(mod_final)$p.value)
)
kable(as.data.frame(lapply(tab_diag_final, rd)),
      caption = "Diagnostica residui - modello selezionato (mod_final)")
Diagnostica residui - modello selezionato (mod_final)
Test Stat p_value
Shapiro 0.97 0.00
Breusch-Pagan 91.77 0.00
Durbin-Watson 1.95 0.12
cook_f <- cooks.distance(mod_final)
lev_f <- hatvalues(mod_final)
rstud_f <- rstudent(mod_final)
idx_inf_f <- which.max(cook_f)

kable(data.frame(
  Osservazione = idx_inf_f,
  Cook = round(cook_f[idx_inf_f], 2),
  Leverage = round(lev_f[idx_inf_f], 2),
  Rstudent = round(rstud_f[idx_inf_f], 2)
), caption = "Osservazione più influente - modello selezionato (mod_final)")
Osservazione più influente - modello selezionato (mod_final)
Osservazione Cook Leverage Rstudent
1551 1551 0.56 0.05 10
soglia_cook <- 4 / nrow(dati)

kable(data.frame(
  Soglia_Cook = round(soglia_cook, 5),
  Numero_osservazioni_oltre_soglia = sum(cook_f > soglia_cook)
),
caption="Verifica soglia Cook (4/n)")
Verifica soglia Cook (4/n)
Soglia_Cook Numero_osservazioni_oltre_soglia
0.0016 116

Il confronto tra i modelli tramite il criterio AIC indica che il modello selezionato tramite procedura stepwise presenta il valore di AIC più basso, risultando quindi un buon compromesso tra capacità esplicativa e complessità del modello. I test diagnostici evidenziano una deviazione dalla normalità dei residui e segnali di eteroschedasticità, mentre non emergono problemi di autocorrelazione dei residui. Considerata l’elevata numerosità campionaria, tali risultati vanno interpretati con cautela e non compromettono l’utilità del modello ai fini descrittivi e predittivi. L’analisi della Cook’s distance individua alcune osservazioni potenzialmente influenti, ma nessuna appare tale da compromettere in modo sostanziale la stabilità complessiva delle stime del modello.

8 Diagnostica modello clinico base (mod1)

RMSE <- sqrt(mean(residuals(mod1)^2, na.rm = TRUE))
kable(data.frame(RMSE=round(RMSE,1)),
      caption="RMSE (training)")
RMSE (training)
RMSE
277.5
par(mfrow=c(2,2))
plot(mod1)

par(mfrow=c(1,1))

tab_diag <- data.frame(
  Test=c("Shapiro","Breusch-Pagan","Durbin-Watson"),
  Stat=c(shapiro.test(residuals(mod1))$statistic,
         bptest(mod1)$statistic,
         dwtest(mod1)$statistic),
  p_value=c(shapiro.test(residuals(mod1))$p.value,
            bptest(mod1)$p.value,
            dwtest(mod1)$p.value)
)
kable(as.data.frame(lapply(tab_diag, rd)),
      caption="Diagnostica residui")
Diagnostica residui
Test Stat p_value
Shapiro 0.98 0.00
Breusch-Pagan 91.80 0.00
Durbin-Watson 1.96 0.17

Il modello clinico base presenta un RMSE pari a circa 277 g, indicando un errore medio di previsione contenuto. I test diagnostici evidenziano una deviazione dalla normalità dei residui e segnali di eteroschedasticità, mentre non emergono problemi di autocorrelazione. Considerata l’elevata numerosità del campione, tali risultati non compromettono l’interpretazione complessiva del modello.

9 Punti influenti

cook <- cooks.distance(mod1)
lev <- hatvalues(mod1)
rstud <- rstudent(mod1)

idx_influente <- which.max(cook)

kable(data.frame(
  Osservazione = idx_influente,
  Cook = round(cook[idx_influente], 3),
  Leverage = round(lev[idx_influente], 3),
  Rstudent = round(rstud[idx_influente], 3)
), caption = "Osservazione più influente")
Osservazione più influente
Osservazione Cook Leverage Rstudent
1551 1551 1.196 0.049 9.872
# Modello stimato senza l’osservazione più influente
mod1_senza <- update(mod1, subset = -idx_influente)

# Confronto capacità esplicativa del modello
kable(data.frame(
  R2_con = round(summary(mod1)$r.squared, 3),
  R2_senza = round(summary(mod1_senza)$r.squared, 3),
  AdjR2_con = round(summary(mod1)$adj.r.squared, 3),
  AdjR2_senza = round(summary(mod1_senza)$adj.r.squared, 3)
), caption = "Sensibilità del modello rimuovendo l’osservazione più influente")
Sensibilità del modello rimuovendo l’osservazione più influente
R2_con R2_senza AdjR2_con AdjR2_senza
0.721 0.731 0.72 0.73
# Stabilità del coefficiente di Gestazione
kable(data.frame(
  BetaGest_con = round(coef(mod1)["Gestazione"], 2),
  BetaGest_senza = round(coef(mod1_senza)["Gestazione"], 2)
), caption = "Stabilità del coefficiente di Gestazione (con/senza osservazione influente)")
Stabilità del coefficiente di Gestazione (con/senza osservazione influente)
BetaGest_con BetaGest_senza
Gestazione 31.69 28.91

L’analisi della Cook’s distance individua l’osservazione 1551 come un possibile outlier nel modello. Nonostante il valore elevato del Rstudent = 9.872, la presenza di tale osservazione non sembra compromettere la stabilità complessiva del modello, anche in considerazione dell’elevata numerosità del campione.In ambito clinico tale deviazione potrebbe essere associata a condizioni specifiche come nascite premature o neonati con peso alla nascita particolarmente elevato o ridotto rispetto alla media.Questo caso potrebbe essere ulteriormente analizzato confrontando il modello stimato con e senza tale osservazione per valutare se il punto influisca significativamente sulle stime dei coefficienti.Il confronto mostra variazioni contenute nei valori di R² (0.721 vs 0.731) e R² aggiustato (0.72 vs 0.73), suggerendo che l’osservazione non altera in modo sostanziale la capacità esplicativa del modello.

10 Differenze per sesso (misure antropometriche)

if("Sesso" %in% names(dati)){

  vars <- c("Peso","Lunghezza","Cranio")

  tab_sesso <- do.call(rbind, lapply(vars, function(v){

  test <- t.test(dati[[v]] ~ dati$Sesso, na.action = na.omit)

  data.frame(
    Variabile = v,
    t = test$statistic,
    p_value = test$p.value
  )
}))

  kable(as.data.frame(lapply(tab_sesso, rd)),
        caption="Differenze per sesso")
}
Differenze per sesso
Variabile t p_value
Peso -12.11 0
Lunghezza -9.58 0
Cranio -7.41 0

I risultati del test t mostrano che esistono differenze statisticamente significative tra maschi e femmine per tutte le principali misure antropometriche considerate. In particolare, peso, lunghezza e diametro cranico risultano mediamente più elevati nei maschi rispetto alle femmine (p < 0.001).

11 Ospedale e tipo parto

if(all(c("Ospedale","Tipo.parto") %in% names(dati))){
  tab <- table(dati$Ospedale, dati$Tipo.parto)
  kable(as.data.frame.matrix(tab),
        caption="Tabella Ospedale × Tipo.parto")
  
  chi <- chisq.test(tab)
  kable(data.frame(
    X2=round(chi$statistic,3),
    df=chi$parameter,
    p_value=round(chi$p.value,4)
  ), caption="Test Chi-quadrato")
}
Test Chi-quadrato
X2 df p_value
X-squared 1.097 2 0.5778

Il test Chi-quadrato mostra che non esiste una relazione statisticamente significativa tra ospedale e tipo di parto (χ² = 1.097, p = 0.5778). Questo suggerisce che la distribuzione tra parti naturali e cesarei è simile nei diversi ospedali considerati.

11.1 Differenze di peso tra ospedali

anova_osp <- aov(Peso ~ Ospedale, data=dati)
ggplot(dati, aes(Ospedale, Peso, fill = Ospedale)) +
  geom_boxplot() +
  theme_classic() +
  labs(title = "Peso alla nascita nei tre ospedali",
       x = "Ospedale",
       y = "Peso (g)")

summary(anova_osp)
##               Df    Sum Sq Mean Sq F value Pr(>F)
## Ospedale       2    936237  468118   1.699  0.183
## Residuals   2497 687952305  275512

L’analisi ANOVA non evidenzia differenze statisticamente significative nel peso medio alla nascita tra i tre ospedali (F = 1.70, p = 0.183). Il boxplot conferma che le distribuzioni del peso sono molto simili tra le tre strutture. Questo suggerisce che eventuali variazioni nel peso alla nascita sono più probabilmente legate alle caratteristiche cliniche della gravidanza e del neonato piuttosto che all’ospedale in cui è avvenuto il parto.

12 Interazione e non linearità

# Modello con interazione
mod_int <- lm(Peso ~ Lunghezza + Cranio + Gestazione +
              Fumatrici + Gestazione:Fumatrici,
              data=dati)

# Modello con termine quadratico
mod_quad <- lm(Peso ~ Lunghezza + Cranio + Gestazione +
               I(Gestazione^2),
               data=dati)

tmp_cmp <- data.frame(
  Modello=c("Lineare (mod1)",
            "Interazione (mod_int)",
            "Quadratico (mod_quad)"),
  AIC=c(AIC(mod1), AIC(mod_int), AIC(mod_quad)),
  BIC=c(BIC(mod1), BIC(mod_int), BIC(mod_quad)),
  R2=c(summary(mod1)$r.squared,
       summary(mod_int)$r.squared,
       summary(mod_quad)$r.squared)
)

kable(as.data.frame(lapply(tmp_cmp, rd)),
      caption="Confronto modelli")
Confronto modelli
Modello AIC BIC R2
Lineare (mod1) 35232.99 35262.11 0.72
Interazione (mod_int) 35235.79 35276.56 0.72
Quadratico (mod_quad) 35227.00 35261.94 0.72
# Test formale dell'interazione
mod_fumo_noint <- lm(Peso ~ Lunghezza + Cranio + Gestazione + Fumatrici, data=dati)

kable(as.data.frame(anova(mod_fumo_noint, mod_int)) |> lapply(rd) |> as.data.frame(),
      caption = "Test formale interazione (confronto modelli annidati)")
Test formale interazione (confronto modelli annidati)
Res.Df RSS Df Sum.of.Sq F Pr..F.
2495 192400004 NA NA NA NA
2494 192360873 1 39130.78 0.51 0.48

Per verificare se l’effetto delle settimane di gestazione sul peso alla nascita vari in funzione del fumo materno è stata testata un’interazione tra gestazione e stato di fumatrice. Inoltre è stato valutato un possibile effetto non lineare della gestazione introducendo un termine quadratico. I risultati mostrano che l’interazione tra gestazione e fumo materno non risulta statisticamente significativa, suggerendo che l’effetto della gestazione sul peso non varia in modo rilevante in funzione dello stato di fumatrice. Il modello con termine quadratico mostra solo un lieve miglioramento in termini di AIC, a fronte di una capacità esplicativa sostanzialmente invariata; pertanto il modello lineare di base risulta preferibile per semplicità interpretativa.

13 Predizione operativa

# --- Predizione con modello clinico base (mod1): solo variabili ecografiche/gestazionali ---
pred1 <- predict(mod1,
                 newdata = data.frame(Lunghezza = 500,
                                      Cranio = 340,
                                      Gestazione = 39),
                 interval = "prediction")

kable(data.frame(
  Modello = "mod1 (clinico base)",
  Peso_previsto = round(pred1[1], 1),
  PI_low = round(pred1[2], 1),
  PI_high = round(pred1[3], 1)
), caption = "Previsione con intervallo (mod1)")
Previsione con intervallo (mod1)
Modello Peso_previsto PI_low PI_high
mod1 (clinico base) 3339.7 2795.1 3884.3
pred_vars <- all.vars(delete.response(terms(mod_final)))  # predittori richiesti dal modello finale

# valori della letteratura
scenario <- list(
  Lunghezza = 500,
  Cranio = 340,
  Gestazione = 39,
  N.gravidanze = 3
)

newd <- as.data.frame(setNames(replicate(length(pred_vars), NA, simplify = FALSE), pred_vars))

for (v in pred_vars) {
  if (v %in% names(scenario)) {
    newd[[v]] <- scenario[[v]]
  } else if (is.numeric(dati[[v]])) {
    newd[[v]] <- median(dati[[v]], na.rm = TRUE)
  } else if (is.factor(dati[[v]])) {
    lv <- levels(dati[[v]])
    # livello più frequente
    mode_lv <- names(sort(table(dati[[v]]), decreasing = TRUE))[1]
    newd[[v]] <- factor(mode_lv, levels = lv)
  } else {
    # fallback per caratteri/altro: valore più frequente
    mode_val <- names(sort(table(dati[[v]]), decreasing = TRUE))[1]
    newd[[v]] <- mode_val
  }
}

predF <- predict(mod_final, newdata = newd, interval = "prediction")

kable(data.frame(
  Modello = "mod_final (selezionato da AIC)",
  Peso_previsto = round(predF[1], 1),
  PI_low = round(predF[2], 1),
  PI_high = round(predF[3], 1)
), caption = "Previsione con intervallo (mod_final) - scenario con N.gravidanze=3")
Previsione con intervallo (mod_final) - scenario con N.gravidanze=3
Modello Peso_previsto PI_low PI_high
mod_final (selezionato da AIC) 3317.2 2779.3 3855.1
# --- Predizione specifica: neonata femmina ---
newd_femmina <- newd

if("Sesso" %in% names(newd_femmina)){
  newd_femmina$Sesso <- factor("F", levels = levels(dati$Sesso))
}

predF_femmina <- predict(mod_final, newdata = newd_femmina, interval = "prediction")

kable(data.frame(
  Modello = "mod_final - scenario neonata femmina",
  Peso_previsto = round(predF_femmina[1], 1),
  PI_low = round(predF_femmina[2], 1),
  PI_high = round(predF_femmina[3], 1)
), caption = "Previsione con intervallo - neonata femmina")
Previsione con intervallo - neonata femmina
Modello Peso_previsto PI_low PI_high
mod_final - scenario neonata femmina 3317.2 2779.3 3855.1

Il modello stimato è stato utilizzato per effettuare una previsione operativa del peso alla nascita in uno scenario clinico ipotetico. Inserendo valori plausibili delle variabili ecografiche e gestazionali (lunghezza 500 mm, diametro cranico 340 mm, 39 settimane di gestazione), il modello clinico base prevede un peso alla nascita di circa 3.34 kg, con un intervallo di predizione compreso tra circa 2.8 kg e 3.9 kg. La previsione ottenuta con il modello finale selezionato tramite AIC risulta molto simile (circa 3.32 kg), indicando una buona stabilità del modello e suggerendo che le principali informazioni predittive sono già catturate dalle variabili antropometriche fondamentali.

14 Visualizzazione finale

ggplot(dati, aes(Gestazione, Peso, col=Fumatrici)) +
  geom_point(alpha=0.5) +
  geom_smooth(method="lm", se=FALSE) +
  theme_classic()+
  labs(title = "Peso vs Gestazione (stratificato per fumo materno)",
       x = "Settimane di gestazione",
       y = "Peso (g)",
       color = "Fumo")

ggplot(dati, aes(x = Sesso, y = Peso, fill = Fumatrici)) +
  geom_boxplot(outlier.alpha = 0.3) +
  theme_classic() +
  labs(title = "Distribuzione del peso per sesso e fumo materno",
       x = "Sesso",
       y = "Peso (g)",
       fill = "Fumo")

I grafici consentono di visualizzare in modo intuitivo alcune delle relazioni emerse dall’analisi statistica. Nel primo grafico si osserva una chiara relazione positiva tra settimane di gestazione e peso alla nascita: neonati nati dopo un numero maggiore di settimane tendono ad avere un peso maggiore. La linea di regressione relativa alle madri fumatrici appare leggermente più bassa rispetto a quella delle non fumatrici, suggerendo una possibile associazione tra fumo materno e peso neonatale inferiore.

Il boxplot mostra inoltre differenze nel peso alla nascita tra maschi e femmine, con i maschi mediamente più pesanti. All’interno di ciascun sesso si osserva una lieve riduzione del peso nei neonati di madri fumatrici rispetto alle non fumatrici.

Tuttavia, in accordo con i risultati della regressione, le variabili che spiegano maggiormente la variabilità del peso alla nascita risultano essere le settimane di gestazione e le misure antropometriche del neonato (lunghezza e diametro cranico), mentre l’effetto del fumo materno appare più contenuto.

15 Conclusioni

L’analisi ha permesso di sviluppare un modello di regressione lineare multipla finalizzato alla previsione del peso alla nascita dei neonati sulla base di variabili cliniche e antropometriche raccolte presso tre ospedali.

Le principali determinanti del peso neonatale sono rappresentate dalla durata della gestazione, dalla lunghezza del neonato e dal diametro cranico. Altre variabili considerate nel modello mostrano un contributo più limitato alla spiegazione della variabilità del peso.

Il modello selezionato tramite criterio AIC mostra una buona capacità esplicativa e una discreta stabilità delle stime, risultando adeguato per finalità descrittive e predittive.