Introduzione

Questo progetto analizza i dati di 2.500 nascite raccolte da tre ospedali, con l’obiettivo di studiare i fattori associati al peso alla nascita e costruire un modello per stimarlo.

L’analisi comprende una prima esplorazione dei dati, alcuni test statistici, un modello di regressione lineare multipla e una previsione applicata a un caso specifico.

I risultati saranno interpretati in modo semplice, tenendo conto anche dei limiti dell’analisi.

1. Pulizia ed esplorazione dei dati

1.1 Importazione e controllo iniziale

Per iniziare, carico il dataset e controllo le dimensioni, le variabili e la presenza di valori mancanti.

# Carico i dati
dati <- read.csv("neonati.csv")

# Controllo la struttura e le dimensioni
dim(dati)
## [1] 2500   10
str(dati)
## 'data.frame':    2500 obs. of  10 variables:
##  $ Anni.madre  : int  26 21 34 28 20 32 26 25 22 23 ...
##  $ N.gravidanze: int  0 2 3 1 0 0 1 0 1 0 ...
##  $ Fumatrici   : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ Gestazione  : int  42 39 38 41 38 40 39 40 40 41 ...
##  $ Peso        : int  3380 3150 3640 3690 3700 3200 3100 3580 3670 3700 ...
##  $ Lunghezza   : int  490 490 500 515 480 495 480 510 500 510 ...
##  $ Cranio      : int  325 345 375 365 335 340 345 349 335 362 ...
##  $ Tipo.parto  : chr  "Nat" "Nat" "Nat" "Nat" ...
##  $ Ospedale    : chr  "osp3" "osp1" "osp2" "osp2" ...
##  $ Sesso       : chr  "M" "F" "M" "M" ...
summary(dati)
##    Anni.madre     N.gravidanze       Fumatrici        Gestazione   
##  Min.   : 0.00   Min.   : 0.0000   Min.   :0.0000   Min.   :25.00  
##  1st Qu.:25.00   1st Qu.: 0.0000   1st Qu.:0.0000   1st Qu.:38.00  
##  Median :28.00   Median : 1.0000   Median :0.0000   Median :39.00  
##  Mean   :28.16   Mean   : 0.9812   Mean   :0.0416   Mean   :38.98  
##  3rd Qu.:32.00   3rd Qu.: 1.0000   3rd Qu.:0.0000   3rd Qu.:40.00  
##  Max.   :46.00   Max.   :12.0000   Max.   :1.0000   Max.   :43.00  
##       Peso        Lunghezza         Cranio     Tipo.parto       
##  Min.   : 830   Min.   :310.0   Min.   :235   Length:2500       
##  1st Qu.:2990   1st Qu.:480.0   1st Qu.:330   Class :character  
##  Median :3300   Median :500.0   Median :340   Mode  :character  
##  Mean   :3284   Mean   :494.7   Mean   :340                     
##  3rd Qu.:3620   3rd Qu.:510.0   3rd Qu.:350                     
##  Max.   :4930   Max.   :565.0   Max.   :390                     
##    Ospedale            Sesso          
##  Length:2500        Length:2500       
##  Class :character   Class :character  
##  Mode  :character   Mode  :character  
##                                       
##                                       
## 
# Controllo i valori mancanti
colSums(is.na(dati))
##   Anni.madre N.gravidanze    Fumatrici   Gestazione         Peso    Lunghezza 
##            0            0            0            0            0            0 
##       Cranio   Tipo.parto     Ospedale        Sesso 
##            0            0            0            0

1.2 Controllo dei valori anomali

Il dataset non presenta valori mancanti, ma alcune variabili hanno valori che potrebbero essere errati. Controllo quindi le osservazioni sospette e le categorie presenti.

# Controllo i valori sospetti
dati[dati$Anni.madre < 12 | dati$Anni.madre > 55, ]
##      Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio
## 1152          1            1         0         41 3250       490    350
## 1380          0            0         0         39 3060       490    330
##      Tipo.parto Ospedale Sesso
## 1152        Nat     osp2     F
## 1380        Nat     osp3     M
dati[dati$Gestazione < 22 | dati$Gestazione > 44, ]
##  [1] Anni.madre   N.gravidanze Fumatrici    Gestazione   Peso        
##  [6] Lunghezza    Cranio       Tipo.parto   Ospedale     Sesso       
## <0 righe> (o 0-length row.names)
dati[dati$Peso < 500 | dati$Peso > 6000, ]
##  [1] Anni.madre   N.gravidanze Fumatrici    Gestazione   Peso        
##  [6] Lunghezza    Cranio       Tipo.parto   Ospedale     Sesso       
## <0 righe> (o 0-length row.names)
dati[dati$Lunghezza < 350 | dati$Lunghezza > 600, ]
##      Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio
## 928          25            0         0         28  830       310    254
## 1551         35            1         0         38 4370       315    374
## 1619         31            0         0         31  990       340    278
## 1780         25            2         0         25  900       325    253
## 2437         28            1         0         27  980       320    265
## 2452         28            0         0         26  930       345    245
##      Tipo.parto Ospedale Sesso
## 928         Nat     osp1     F
## 1551        Nat     osp3     F
## 1619        Ces     osp2     F
## 1780        Nat     osp3     F
## 2437        Nat     osp1     M
## 2452        Ces     osp3     F
dati[dati$Cranio < 250 | dati$Cranio > 450, ]
##      Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio
## 2175         37            8         0         28  930       355    235
## 2452         28            0         0         26  930       345    245
##      Tipo.parto Ospedale Sesso
## 2175        Nat     osp1     F
## 2452        Ces     osp3     F
# Controllo le categorie
table(dati$Fumatrice)
## < table of extent 0 >
table(dati$N.gravidanze)
## 
##    0    1    2    3    4    5    6    7    8    9   10   11   12 
## 1096  818  340  150   48   21   11    1    8    2    3    1    1
table(dati$Tipo.parto)
## 
##  Ces  Nat 
##  728 1772
table(dati$Ospedale)
## 
## osp1 osp2 osp3 
##  816  849  835
table(dati$Sesso)
## 
##    F    M 
## 1256 1244

1.3 Riepilogo delle anomalie

Riassumo il numero di valori sospetti per ogni variabile, così da capire quali dati richiedono una correzione prima delle analisi.

# Conto le osservazioni sospette
anomalie <- data.frame(
  Variabile = c("Età madre", "Gestazione", "Peso",
                "Lunghezza", "Cranio"),
  Valori_sospetti = c(
    sum(dati$Anni.madre < 12 | dati$Anni.madre > 55),
    sum(dati$Gestazione < 22 | dati$Gestazione > 44),
    sum(dati$Peso < 500 | dati$Peso > 6000),
    sum(dati$Lunghezza < 350 | dati$Lunghezza > 600),
    sum(dati$Cranio < 250 | dati$Cranio > 450)
  )
)

print(anomalie, row.names = FALSE)
##   Variabile Valori_sospetti
##   Età madre               2
##  Gestazione               0
##        Peso               0
##   Lunghezza               6
##      Cranio               2

1.4 Verifica delle osservazioni sospette

Controllo più nel dettaglio i valori sospetti per capire quali potrebbero essere errori e quali invece osservazioni reali.

# Individuo le righe con almeno un valore sospetto
sospetti <- which(
  dati$Anni.madre < 12 | dati$Anni.madre > 55 |
  dati$Gestazione < 22 | dati$Gestazione > 44 |
  dati$Peso < 500 | dati$Peso > 6000 |
  dati$Lunghezza < 350 | dati$Lunghezza > 600 |
  dati$Cranio < 250 | dati$Cranio > 450
)

# Mostro le osservazioni e i loro numeri di riga
dettaglio <- data.frame(
  Riga = sospetti,
  dati[sospetti, ]
)

print(dettaglio, row.names = FALSE)
##  Riga Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio
##   928         25            0         0         28  830       310    254
##  1152          1            1         0         41 3250       490    350
##  1380          0            0         0         39 3060       490    330
##  1551         35            1         0         38 4370       315    374
##  1619         31            0         0         31  990       340    278
##  1780         25            2         0         25  900       325    253
##  2175         37            8         0         28  930       355    235
##  2437         28            1         0         27  980       320    265
##  2452         28            0         0         26  930       345    245
##  Tipo.parto Ospedale Sesso
##         Nat     osp1     F
##         Nat     osp2     F
##         Nat     osp3     M
##         Nat     osp3     F
##         Ces     osp2     F
##         Nat     osp3     F
##         Nat     osp1     F
##         Nat     osp1     M
##         Ces     osp3     F

1.5 Pulizia e preparazione dei dati

Il controllo ha evidenziato due età materne non plausibili (0 e 1 anno), che vengono considerate mancanti. Le altre osservazioni sospette vengono mantenute perché potrebbero riferirsi a nascite premature.

Converto anche le misure di lunghezza e diametro craniale da millimetri a centimetri e preparo le variabili categoriche per le analisi successive.

# Creo una copia del dataset originale
dati_puliti <- dati

# Correggo le età materne non plausibili
dati_puliti$Anni.madre[dati_puliti$Anni.madre < 12] <- NA

# Converto le misure in centimetri
dati_puliti$Lunghezza <- dati_puliti$Lunghezza / 10
dati_puliti$Cranio <- dati_puliti$Cranio / 10

# Converto le variabili categoriche in fattori

# Converto la variabile in fattore
dati_puliti$Fumatrici <- factor(dati_puliti$Fumatrici,
                               levels = c(0, 1),
                               labels = c("No", "Si"))

dati_puliti$Tipo.parto <- factor(dati_puliti$Tipo.parto,
                                levels = c("Nat", "Ces"),
                                labels = c("Naturale", "Cesareo"))

dati_puliti$Ospedale <- factor(dati_puliti$Ospedale,
                              levels = c("osp1", "osp2", "osp3"))

dati_puliti$Sesso <- factor(dati_puliti$Sesso,
                           levels = c("F", "M"))

# Controllo il risultato
summary(dati_puliti)
##    Anni.madre     N.gravidanze     Fumatrici   Gestazione         Peso     
##  Min.   :13.00   Min.   : 0.0000   No:2396   Min.   :25.00   Min.   : 830  
##  1st Qu.:25.00   1st Qu.: 0.0000   Si: 104   1st Qu.:38.00   1st Qu.:2990  
##  Median :28.00   Median : 1.0000             Median :39.00   Median :3300  
##  Mean   :28.19   Mean   : 0.9812             Mean   :38.98   Mean   :3284  
##  3rd Qu.:32.00   3rd Qu.: 1.0000             3rd Qu.:40.00   3rd Qu.:3620  
##  Max.   :46.00   Max.   :12.0000             Max.   :43.00   Max.   :4930  
##  NA's   :2                                                                 
##    Lunghezza         Cranio        Tipo.parto   Ospedale   Sesso   
##  Min.   :31.00   Min.   :23.5   Naturale:1772   osp1:816   F:1256  
##  1st Qu.:48.00   1st Qu.:33.0   Cesareo : 728   osp2:849   M:1244  
##  Median :50.00   Median :34.0                   osp3:835           
##  Mean   :49.47   Mean   :34.0                                      
##  3rd Qu.:51.00   3rd Qu.:35.0                                      
##  Max.   :56.50   Max.   :39.0                                      
## 
colSums(is.na(dati_puliti))
##   Anni.madre N.gravidanze    Fumatrici   Gestazione         Peso    Lunghezza 
##            2            0            0            0            0            0 
##       Cranio   Tipo.parto     Ospedale        Sesso 
##            0            0            0            0

1.6 Distribuzione delle variabili quantitative

Per capire meglio come sono distribuiti i dati, utilizzo istogrammi e boxplot. Questi grafici permettono di osservare i valori più frequenti e individuare eventuali valori estremi.

# Seleziono le variabili quantitative
variabili <- c("Anni.madre", "N.gravidanze", "Gestazione",
               "Peso", "Lunghezza", "Cranio")

# Istogrammi
par(mfrow = c(2, 3), mar = c(4, 4, 3, 1))

for (v in variabili) {
  hist(dati_puliti[[v]],
       main = v,
       xlab = v,
       col = "lightblue",
       border = "white")
}

# Boxplot
par(mfrow = c(2, 3), mar = c(4, 4, 3, 1))

for (v in variabili) {
  boxplot(dati_puliti[[v]],
          main = v,
          col = "lightgreen")
}

# Ripristino la finestra grafica
par(mfrow = c(1, 1))

Interpretazione dei risultati

La maggior parte delle madri ha un’età compresa tra 25 e 32 anni e presenta poche gravidanze precedenti.

Le nascite si concentrano soprattutto tra la 38ª e la 40ª settimana di gestazione. Il peso dei neonati è generalmente vicino ai 3.300 g, mentre la lunghezza è intorno ai 50 cm e il diametro craniale ai 34 cm.

I boxplot evidenziano diversi valori estremi, soprattutto per peso, lunghezza, diametro craniale e settimane di gestazione. Questi valori potrebbero essere legati alle nascite premature e, non essendo necessariamente errori, sono stati mantenuti nelle analisi.

1.7 Distribuzione delle variabili categoriche

Controllo la frequenza delle diverse categorie per capire come sono distribuite le nascite nel dataset.

# Seleziono le variabili categoriche
categoriche <- c("Fumatrici", "Tipo.parto", "Ospedale", "Sesso")

# Grafici a barre
par(mfrow = c(2, 2), mar = c(4, 4, 3, 1))

for (v in categoriche) {
  barplot(table(dati_puliti[[v]]),
          main = v,
          ylab = "Numero di nascite",
          col = "lightblue")
}

par(mfrow = c(1, 1))

# Tabella delle frequenze e percentuali
for (v in categoriche) {
  cat("\n", v, "\n")
  print(table(dati_puliti[[v]]))
  print(round(prop.table(table(dati_puliti[[v]])) * 100, 1))
}
## 
##  Fumatrici 
## 
##   No   Si 
## 2396  104 
## 
##   No   Si 
## 95.8  4.2 
## 
##  Tipo.parto 
## 
## Naturale  Cesareo 
##     1772      728 
## 
## Naturale  Cesareo 
##     70.9     29.1 
## 
##  Ospedale 
## 
## osp1 osp2 osp3 
##  816  849  835 
## 
## osp1 osp2 osp3 
## 32.6 34.0 33.4 
## 
##  Sesso 
## 
##    F    M 
## 1256 1244 
## 
##    F    M 
## 50.2 49.8

Interpretazione dei risultati

La maggior parte delle madri non fuma (95,8%), mentre le fumatrici rappresentano il 4,2% del campione.

Il parto naturale è il più frequente (70,9%), mentre il cesareo riguarda il 29,1% delle nascite.

Le osservazioni sono distribuite in modo abbastanza uniforme tra i tre ospedali e anche tra i due sessi, con il 50,2% di femmine e il 49,8% di maschi.

Questa distribuzione permette di confrontare gruppi con numerosità simili per ospedale e sesso. Le madri fumatrici, invece, sono molto meno numerose.

2. Verifica delle ipotesi cliniche

2.1 Differenze nel ricorso al cesareo tra ospedali

Voglio verificare se la percentuale di parti cesarei cambia tra i tre ospedali.

Le ipotesi sono:

  • H0: il tipo di parto è indipendente dall’ospedale.
  • H1: esiste un’associazione tra tipo di parto e ospedale.

Utilizzo il test chi-quadrato di Pearson perché entrambe le variabili sono categoriche.

# Creo la tabella di contingenza
tabella_cesarei <- table(dati_puliti$Ospedale,
                        dati_puliti$Tipo.parto)

tabella_cesarei
##       
##        Naturale Cesareo
##   osp1      574     242
##   osp2      595     254
##   osp3      603     232
# Calcolo le percentuali per ospedale
round(prop.table(tabella_cesarei, 1) * 100, 1)
##       
##        Naturale Cesareo
##   osp1     70.3    29.7
##   osp2     70.1    29.9
##   osp3     72.2    27.8
# Test chi-quadrato
test_cesarei <- chisq.test(tabella_cesarei)
test_cesarei
## 
##  Pearson's Chi-squared test
## 
## data:  tabella_cesarei
## X-squared = 1.0972, df = 2, p-value = 0.5778
# Controllo le frequenze attese
test_cesarei$expected
##       
##        Naturale  Cesareo
##   osp1 578.3808 237.6192
##   osp2 601.7712 247.2288
##   osp3 591.8480 243.1520

Interpretazione dei risultati

Le percentuali di parti cesarei sono abbastanza simili nei tre ospedali: 29,7% nel primo, 29,9% nel secondo e 27,8% nel terzo.

Il test chi-quadrato restituisce un p-value di 0,578, superiore a 0,05. Non possiamo quindi affermare che esistano differenze statisticamente significative nel ricorso al cesareo tra gli ospedali.

Le differenze osservate sono piccole, ma questo non dimostra che i tre ospedali si comportino esattamente allo stesso modo.

2.2 Confronto con i valori di riferimento italiani

Verifico se il peso e la lunghezza medi dei neonati sono diversi dai valori di riferimento italiani: 3.300 g e 50 cm.

Per il peso:

  • H0: il peso medio è uguale a 3.300 g.
  • H1: il peso medio è diverso da 3.300 g.

Per la lunghezza:

  • H0: la lunghezza media è uguale a 50 cm.
  • H1: la lunghezza media è diversa da 50 cm.

Utilizzo due test t a un campione, perché confronto le medie del campione con valori di riferimento e non conosco la deviazione standard della popolazione.

# Test sul peso medio
test_peso <- t.test(dati_puliti$Peso, mu = 3300)
test_peso
## 
##  One Sample t-test
## 
## data:  dati_puliti$Peso
## t = -1.516, df = 2499, p-value = 0.1296
## alternative hypothesis: true mean is not equal to 3300
## 95 percent confidence interval:
##  3263.490 3304.672
## sample estimates:
## mean of x 
##  3284.081
# Test sulla lunghezza media
test_lunghezza <- t.test(dati_puliti$Lunghezza, mu = 50)
test_lunghezza
## 
##  One Sample t-test
## 
## data:  dati_puliti$Lunghezza
## t = -10.084, df = 2499, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 50
## 95 percent confidence interval:
##  49.36598 49.57242
## sample estimates:
## mean of x 
##   49.4692

Interpretazione dei risultati

Il peso medio dei neonati è di 3.284 g, leggermente inferiore al riferimento italiano di 3.300 g. Il p-value è 0,130, quindi la differenza non è statisticamente significativa. L’intervallo di confidenza al 95% va da 3.263 a 3.305 g e comprende il valore di riferimento.

La lunghezza media è di 49,47 cm, circa 0,53 cm in meno rispetto ai 50 cm di riferimento. In questo caso il p-value è inferiore a 0,001 e l’intervallo di confidenza va da 49,37 a 49,57 cm.

Possiamo quindi dire che il peso medio è compatibile con il riferimento, mentre la lunghezza media risulta statisticamente inferiore. La differenza di lunghezza è comunque contenuta e non possiamo stabilire da questi dati se abbia un’importanza clinica.

2.3 Differenze delle misure antropometriche tra maschi e femmine

Verifico se peso, lunghezza e diametro craniale sono diversi tra neonati maschi e femmine.

Per ciascuna misura considero:

  • H0: la media è uguale nei due sessi.
  • H1: la media è diversa tra maschi e femmine.

Utilizzo il test t di Welch per campioni indipendenti, perché confronto due gruppi distinti senza assumere che abbiano la stessa varianza.

# Confronto il peso
t.test(Peso ~ Sesso, data = dati_puliti)
## 
##  Welch Two Sample t-test
## 
## data:  Peso by Sesso
## t = -12.106, df = 2490.7, p-value < 2.2e-16
## alternative hypothesis: true difference in means between group F and group M is not equal to 0
## 95 percent confidence interval:
##  -287.1051 -207.0615
## sample estimates:
## mean in group F mean in group M 
##        3161.132        3408.215
# Confronto la lunghezza
t.test(Lunghezza ~ Sesso, data = dati_puliti)
## 
##  Welch Two Sample t-test
## 
## data:  Lunghezza by Sesso
## t = -9.582, df = 2459.3, p-value < 2.2e-16
## alternative hypothesis: true difference in means between group F and group M is not equal to 0
## 95 percent confidence interval:
##  -1.1929470 -0.7876273
## sample estimates:
## mean in group F mean in group M 
##        48.97643        49.96672
# Confronto il diametro craniale
t.test(Cranio ~ Sesso, data = dati_puliti)
## 
##  Welch Two Sample t-test
## 
## data:  Cranio by Sesso
## t = -7.4102, df = 2491.4, p-value = 1.718e-13
## alternative hypothesis: true difference in means between group F and group M is not equal to 0
## 95 percent confidence interval:
##  -0.6089912 -0.3541270
## sample estimates:
## mean in group F mean in group M 
##        33.76330        34.24486
# Visualizzo le differenze
par(mfrow = c(1, 3), mar = c(4, 4, 3, 1))

boxplot(Peso ~ Sesso, data = dati_puliti,
        main = "Peso", ylab = "Grammi",
        col = "lightblue")

boxplot(Lunghezza ~ Sesso, data = dati_puliti,
        main = "Lunghezza", ylab = "Centimetri",
        col = "lightblue")

boxplot(Cranio ~ Sesso, data = dati_puliti,
        main = "Diametro craniale", ylab = "Centimetri",
        col = "lightblue")

par(mfrow = c(1, 1))

Interpretazione dei risultati

Dai boxplot si osserva che i neonati maschi tendono ad avere misure antropometriche maggiori rispetto alle femmine.

La lunghezza media è di 48,98 cm nelle femmine e 49,97 cm nei maschi, con una differenza di circa 0,99 cm. Il p-value è inferiore a 0,001, quindi la differenza è statisticamente significativa.

Anche il diametro craniale risulta maggiore nei maschi: 34,24 cm contro 33,76 cm nelle femmine, con una differenza di circa 0,48 cm. Anche in questo caso il p-value è inferiore a 0,001.

Questi risultati indicano differenze medie tra i due sessi, anche se le distribuzioni si sovrappongono ampiamente.

Anche il peso medio è maggiore nei maschi, con 3.408 g rispetto ai 3.161 g delle femmine. La differenza è di circa 247 g ed è statisticamente significativa (p-value < 0,001). L’intervallo di confidenza al 95% indica una differenza compresa tra circa 207 e 287 g.

Nel complesso, i tre test mostrano differenze significative tra maschi e femmine per peso, lunghezza e diametro craniale. Queste differenze riguardano le medie dei gruppi e non necessariamente ogni singolo neonato.

3. Correlazioni e regressione lineare multipla

3.1 Relazioni tra variabili quantitative

Prima di costruire il modello, controllo le correlazioni tra il peso alla nascita e le altre variabili quantitative. Utilizzo il coefficiente di Pearson e gli scatterplot per capire quali relazioni sono più evidenti.

# Seleziono le variabili quantitative
variabili_num <- dati_puliti[, c("Anni.madre", "N.gravidanze",
                                "Gestazione", "Peso",
                                "Lunghezza", "Cranio")]

# Matrice di correlazione
round(cor(variabili_num, use = "complete.obs"), 2)
##              Anni.madre N.gravidanze Gestazione  Peso Lunghezza Cranio
## Anni.madre         1.00         0.38      -0.13 -0.02     -0.06   0.02
## N.gravidanze       0.38         1.00      -0.10  0.00     -0.06   0.04
## Gestazione        -0.13        -0.10       1.00  0.59      0.62   0.46
## Peso              -0.02         0.00       0.59  1.00      0.80   0.70
## Lunghezza         -0.06        -0.06       0.62  0.80      1.00   0.60
## Cranio             0.02         0.04       0.46  0.70      0.60   1.00
# Scatterplot del peso rispetto agli altri predittori
par(mfrow = c(2, 3), mar = c(4, 4, 3, 1))

for (v in c("Anni.madre", "N.gravidanze", "Gestazione",
            "Lunghezza", "Cranio")) {
  plot(dati_puliti[[v]], dati_puliti$Peso,
       main = paste("Peso e", v),
       xlab = v,
       ylab = "Peso (g)",
       pch = 20,
       col = "steelblue")
}

par(mfrow = c(1, 1))

Interpretazione dei risultati

Il peso alla nascita presenta una correlazione positiva soprattutto con la lunghezza (r = 0,80), il diametro craniale (r = 0,70) e le settimane di gestazione (r = 0,59).

Questo significa che, in generale, i neonati più lunghi, con un diametro craniale maggiore e nati dopo più settimane di gestazione tendono a pesare di più.

L’età materna e il numero di gravidanze precedenti mostrano invece correlazioni molto deboli con il peso.

Gli scatterplot confermano queste relazioni. Si nota inoltre una correlazione tra lunghezza e gestazione (r = 0,62), che sarà utile considerare quando analizzeremo il modello multiplo.

Queste correlazioni indicano delle associazioni tra variabili, ma non dimostrano rapporti di causa-effetto.

3.2 Modello di regressione multipla completo

Costruisco un primo modello di regressione lineare multipla utilizzando tutte le variabili disponibili come predittori del peso alla nascita.

L’obiettivo è capire quali variabili sono maggiormente associate al peso, tenendo conto contemporaneamente delle altre.

# Creo il modello completo
mod1 <- lm(Peso ~ Anni.madre + N.gravidanze + Fumatrici +
             Gestazione + Lunghezza + Cranio +
             Tipo.parto + Ospedale + Sesso,
           data = dati_puliti)

# Visualizzo i risultati
summary(mod1)
## 
## Call:
## lm(formula = Peso ~ Anni.madre + N.gravidanze + Fumatrici + Gestazione + 
##     Lunghezza + Cranio + Tipo.parto + Ospedale + Sesso, data = dati_puliti)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1123.26  -181.53   -14.45   161.05  2611.89 
## 
## Coefficients:
##                     Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       -6706.1625   141.1085 -47.525  < 2e-16 ***
## Anni.madre            0.8018     1.1467   0.699   0.4845    
## N.gravidanze         11.3812     4.6686   2.438   0.0148 *  
## FumatriciSi         -30.2741    27.5492  -1.099   0.2719    
## Gestazione           32.5773     3.8208   8.526  < 2e-16 ***
## Lunghezza           102.9218     3.0088  34.207  < 2e-16 ***
## Cranio              104.7221     4.2627  24.567  < 2e-16 ***
## Tipo.partoCesareo   -29.6335    12.0905  -2.451   0.0143 *  
## Ospedaleosp2        -11.0912    13.4471  -0.825   0.4096    
## Ospedaleosp3         28.2495    13.5054   2.092   0.0366 *  
## SessoM               77.5723    11.1865   6.934 5.18e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 274 on 2487 degrees of freedom
##   (2 osservazioni eliminate a causa di valori mancanti)
## Multiple R-squared:  0.7289, Adjusted R-squared:  0.7278 
## F-statistic: 668.7 on 10 and 2487 DF,  p-value: < 2.2e-16
# Controllo il numero di osservazioni utilizzate
nobs(mod1)
## [1] 2498
# Calcolo AIC e BIC
AIC(mod1)
## [1] 35145.57
BIC(mod1)
## [1] 35215.45

Interpretazione dei risultati

Il modello completo spiega circa il 72,9% della variabilità del peso alla nascita (R² = 0,729), con un errore standard residuo di circa 274 g.

I coefficienti indicano come cambia mediamente il peso stimato al variare di una caratteristica, mantenendo costanti le altre.

Variabile Coefficiente Interpretazione
Età materna +0,80 g Associazione molto debole, non significativa (p = 0,485).
Gravidanze precedenti +11,38 g Circa 11 g in più per ogni gravidanza precedente (p = 0,015).
Fumo materno -30,27 g Le fumatrici hanno un peso stimato inferiore di circa 30 g, ma la differenza non è significativa (p = 0,272).
Gestazione +32,58 g Circa 33 g in più per ogni settimana aggiuntiva (p < 0,001).
Lunghezza +102,92 g Circa 103 g in più per ogni centimetro (p < 0,001).
Diametro craniale +104,72 g Circa 105 g in più per ogni centimetro (p < 0,001).
Parto cesareo -29,63 g Circa 30 g in meno rispetto al parto naturale (p = 0,014).
Ospedale 2 -11,09 g Differenza non significativa rispetto all’ospedale 1 (p = 0,410).
Ospedale 3 +28,25 g Circa 28 g in più rispetto all’ospedale 1 (p = 0,037).
Sesso maschile +77,57 g Circa 78 g in più rispetto alle femmine (p < 0,001).

Le associazioni più evidenti riguardano lunghezza, diametro craniale e gestazione. L’età materna e il fumo non risultano significativi nel modello completo.

Questi risultati mostrano delle associazioni statistiche e non dimostrano necessariamente rapporti di causa-effetto.

3.3 Riduzione del modello

Provo a semplificare il modello eliminando inizialmente l’età materna, che non risulta significativa. Confronto poi i due modelli per verificare se la sua esclusione peggiora l’adattamento.

# Creo il modello senza età materna
mod2 <- update(mod1, ~ . - Anni.madre)

# Confronto i risultati
summary(mod2)
## 
## Call:
## lm(formula = Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + 
##     Cranio + Tipo.parto + Ospedale + Sesso, data = dati_puliti)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1113.93  -180.11   -16.36   160.58  2616.96 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       -6678.571    135.543 -49.273  < 2e-16 ***
## N.gravidanze         12.608      4.338   2.906  0.00369 ** 
## FumatriciSi         -30.309     27.536  -1.101  0.27113    
## Gestazione           32.250      3.797   8.494  < 2e-16 ***
## Lunghezza           102.944      3.007  34.239  < 2e-16 ***
## Cranio              104.876      4.255  24.651  < 2e-16 ***
## Tipo.partoCesareo   -29.535     12.083  -2.444  0.01458 *  
## Ospedaleosp2        -11.082     13.436  -0.825  0.40957    
## Ospedaleosp3         28.366     13.490   2.103  0.03559 *  
## SessoM               77.621     11.176   6.945 4.81e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 273.9 on 2490 degrees of freedom
## Multiple R-squared:  0.7288, Adjusted R-squared:  0.7278 
## F-statistic: 743.6 on 9 and 2490 DF,  p-value: < 2.2e-16
# Confronto i modelli sugli stessi dati
dati_confronto <- dati_puliti[complete.cases(
  dati_puliti[, c("Anni.madre", "N.gravidanze", "Fumatrici",
                 "Gestazione", "Lunghezza", "Cranio",
                 "Tipo.parto", "Ospedale", "Sesso")]), ]

mod2_confronto <- lm(formula(mod2), data = dati_confronto)

anova(mod2_confronto, mod1)
## Analysis of Variance Table
## 
## Model 1: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio + 
##     Tipo.parto + Ospedale + Sesso
## Model 2: Peso ~ Anni.madre + N.gravidanze + Fumatrici + Gestazione + Lunghezza + 
##     Cranio + Tipo.parto + Ospedale + Sesso
##   Res.Df       RSS Df Sum of Sq      F Pr(>F)
## 1   2488 186779904                           
## 2   2487 186743194  1     36710 0.4889 0.4845
# Confronto R² aggiustato, AIC e BIC
AIC(mod1, mod2_confronto)
##                df      AIC
## mod1           12 35145.57
## mod2_confronto 11 35144.06
BIC(mod1, mod2_confronto)
##                df      BIC
## mod1           12 35215.45
## mod2_confronto 11 35208.12

Interpretazione dei risultati

Eliminando l’età materna, il modello mantiene praticamente lo stesso R² aggiustato (0,728).

Il confronto ANOVA non mostra un peggioramento significativo (p = 0,485). Anche AIC e BIC diminuiscono leggermente, indicando che il modello più semplice è preferibile.

Decido quindi di escludere l’età materna dai predittori.

3.4 Valutazione della variabile ospedale

Verifico se mantenere la variabile ospedale migliora il modello. Per farlo confronto il modello precedente con una versione senza questo predittore.

# Uso le stesse osservazioni per il confronto
mod2_base <- mod2_confronto

# Creo il modello senza ospedale
mod3 <- update(mod2_base, ~ . - Ospedale)

# Confronto i modelli
summary(mod3)
## 
## Call:
## lm(formula = Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + 
##     Cranio + Tipo.parto + Sesso, data = dati_confronto)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1129.88  -181.36   -16.24   160.63  2634.62 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       -6678.385    135.662 -49.228  < 2e-16 ***
## N.gravidanze         12.993      4.344   2.991  0.00281 ** 
## FumatriciSi         -31.882     27.580  -1.156  0.24780    
## Gestazione           32.597      3.804   8.569  < 2e-16 ***
## Lunghezza           102.684      3.011  34.098  < 2e-16 ***
## Cranio              105.015      4.262  24.637  < 2e-16 ***
## Tipo.partoCesareo   -30.424     12.104  -2.514  0.01201 *  
## SessoM               78.103     11.200   6.974 3.94e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 274.4 on 2490 degrees of freedom
## Multiple R-squared:  0.7278, Adjusted R-squared:  0.7271 
## F-statistic: 951.3 on 7 and 2490 DF,  p-value: < 2.2e-16
anova(mod3, mod2_base)
## Analysis of Variance Table
## 
## Model 1: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio + 
##     Tipo.parto + Sesso
## Model 2: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio + 
##     Tipo.parto + Ospedale + Sesso
##   Res.Df       RSS Df Sum of Sq      F   Pr(>F)   
## 1   2490 187473818                                
## 2   2488 186779904  2    693914 4.6216 0.009921 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Confronto AIC e BIC
AIC(mod2_base, mod3)
##           df      AIC
## mod2_base 11 35144.06
## mod3       9 35149.33
BIC(mod2_base, mod3)
##           df      BIC
## mod2_base 11 35208.12
## mod3       9 35201.73

Interpretazione dei risultati

Eliminando la variabile Ospedale, l’R² aggiustato diminuisce leggermente da 0,7278 a 0,7271.

Il test ANOVA indica un peggioramento statisticamente significativo (p = 0,010). L’AIC favorisce il modello con Ospedale, mentre il BIC preferisce quello più semplice.

Dato che l’azienda è interessata anche alle differenze tra strutture, decido per il momento di mantenere questa variabile.

3.5 Valutazione di una relazione non lineare

Dallo scatterplot tra gestazione e peso si nota che la relazione potrebbe non essere perfettamente lineare.

Provo quindi ad aggiungere un termine quadratico per verificare se migliora il modello.

# Parto dal modello senza età materna
mod_base <- mod2_base

# Aggiungo il termine quadratico della gestazione
mod_quadratico <- update(mod_base, ~ . + I(Gestazione^2))

# Controllo il nuovo modello
summary(mod_quadratico)
## 
## Call:
## lm(formula = Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + 
##     Cranio + Tipo.parto + Ospedale + Sesso + I(Gestazione^2), 
##     data = dati_confronto)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1143.27  -181.03   -12.92   162.57  2637.95 
## 
## Coefficients:
##                     Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       -4792.2523   897.3309  -5.341 1.01e-07 ***
## N.gravidanze         12.6685     4.3371   2.921  0.00352 ** 
## FumatriciSi         -29.2938    27.5312  -1.064  0.28742    
## Gestazione          -73.0509    49.6761  -1.471  0.14154    
## Lunghezza           103.8794     3.0403  34.168  < 2e-16 ***
## Cranio              105.7828     4.2751  24.744  < 2e-16 ***
## Tipo.partoCesareo   -29.2306    12.0824  -2.419  0.01562 *  
## Ospedaleosp2        -10.1949    13.4394  -0.759  0.44817    
## Ospedaleosp3         28.1888    13.4900   2.090  0.03675 *  
## SessoM               75.5911    11.2186   6.738 1.99e-11 ***
## I(Gestazione^2)       1.4064     0.6612   2.127  0.03352 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 273.8 on 2487 degrees of freedom
## Multiple R-squared:  0.7293, Adjusted R-squared:  0.7283 
## F-statistic: 670.2 on 10 and 2487 DF,  p-value: < 2.2e-16
# Confronto i due modelli
anova(mod_base, mod_quadratico)
## Analysis of Variance Table
## 
## Model 1: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio + 
##     Tipo.parto + Ospedale + Sesso
## Model 2: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio + 
##     Tipo.parto + Ospedale + Sesso + I(Gestazione^2)
##   Res.Df       RSS Df Sum of Sq     F  Pr(>F)  
## 1   2488 186779904                             
## 2   2487 186440757  1    339147 4.524 0.03352 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Confronto AIC e BIC
AIC(mod_base, mod_quadratico)
##                df      AIC
## mod_base       11 35144.06
## mod_quadratico 12 35141.52
BIC(mod_base, mod_quadratico)
##                df      BIC
## mod_base       11 35208.12
## mod_quadratico 12 35211.40

Interpretazione dei risultati

Aggiungendo il termine quadratico della gestazione, l’R² aggiustato aumenta leggermente da 0,7278 a 0,7283.

Il miglioramento risulta statisticamente significativo (p = 0,034), ma è molto piccolo. L’AIC favorisce il modello quadratico, mentre il BIC preferisce quello lineare.

Per semplicità, decido di mantenere il modello lineare, che offre risultati molto simili ed è più facile da interpretare.

3.6 Valutazione di un’interazione

Verifico se la relazione tra settimane di gestazione e peso alla nascita cambia tra madri fumatrici e non fumatrici.

Aggiungo quindi un termine di interazione e confronto il nuovo modello con quello precedente.

# Aggiungo l'interazione tra gestazione e fumo
mod_interazione <- update(mod_base, ~ . + Gestazione:Fumatrici)

# Controllo i risultati
summary(mod_interazione)
## 
## Call:
## lm(formula = Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + 
##     Cranio + Tipo.parto + Ospedale + Sesso + Fumatrici:Gestazione, 
##     data = dati_confronto)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -1113.3  -180.9   -16.6   161.1  2616.2 
## 
## Coefficients:
##                         Estimate Std. Error t value Pr(>|t|)    
## (Intercept)            -6697.460    136.563 -49.043  < 2e-16 ***
## N.gravidanze              12.634      4.340   2.911  0.00363 ** 
## FumatriciSi              839.377    755.923   1.110  0.26693    
## Gestazione                32.885      3.833   8.579  < 2e-16 ***
## Lunghezza                102.858      3.009  34.187  < 2e-16 ***
## Cranio                   104.817      4.257  24.624  < 2e-16 ***
## Tipo.partoCesareo        -29.865     12.090  -2.470  0.01357 *  
## Ospedaleosp2             -10.619     13.446  -0.790  0.42978    
## Ospedaleosp3              28.858     13.501   2.137  0.03266 *  
## SessoM                    78.261     11.197   6.989 3.53e-12 ***
## FumatriciSi:Gestazione   -22.156     19.242  -1.151  0.24967    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 274 on 2487 degrees of freedom
## Multiple R-squared:  0.729,  Adjusted R-squared:  0.7279 
## F-statistic:   669 on 10 and 2487 DF,  p-value: < 2.2e-16
# Confronto i modelli
anova(mod_base, mod_interazione)
## Analysis of Variance Table
## 
## Model 1: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio + 
##     Tipo.parto + Ospedale + Sesso
## Model 2: Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio + 
##     Tipo.parto + Ospedale + Sesso + Fumatrici:Gestazione
##   Res.Df       RSS Df Sum of Sq      F Pr(>F)
## 1   2488 186779904                           
## 2   2487 186680389  1     99515 1.3258 0.2497
# Confronto AIC e BIC
AIC(mod_base, mod_interazione)
##                 df      AIC
## mod_base        11 35144.06
## mod_interazione 12 35144.73
BIC(mod_base, mod_interazione)
##                 df      BIC
## mod_base        11 35208.12
## mod_interazione 12 35214.61

Interpretazione dei risultati

L’interazione tra fumo materno e settimane di gestazione non risulta statisticamente significativa (p = 0,250).

L’R² aggiustato rimane praticamente invariato, mentre AIC e BIC aumentano leggermente.

Decido quindi di non inserire questa interazione nel modello, perché non porta un miglioramento utile.

3.7 Scelta del modello essenziale

Dopo i confronti effettuati, scelgo un modello più semplice rispetto a quello iniziale, eliminando l’età materna e senza aggiungere termini quadratici o interazioni.

Mantengo le altre variabili e controllo la presenza di multicollinearità.

# Seleziono il modello
mod_finale <- mod2_base

# Riepilogo del modello
summary(mod_finale)
## 
## Call:
## lm(formula = formula(mod2), data = dati_confronto)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1113.82  -180.30   -16.22   160.66  2616.32 
## 
## Coefficients:
##                    Estimate Std. Error t value Pr(>|t|)    
## (Intercept)       -6678.954    135.623 -49.247  < 2e-16 ***
## N.gravidanze         12.583      4.340   2.899  0.00377 ** 
## FumatriciSi         -30.427     27.545  -1.105  0.26944    
## Gestazione           32.300      3.800   8.501  < 2e-16 ***
## Lunghezza           102.916      3.008  34.209  < 2e-16 ***
## Cranio              104.874      4.257  24.638  < 2e-16 ***
## Tipo.partoCesareo   -29.665     12.089  -2.454  0.01420 *  
## Ospedaleosp2        -10.951     13.444  -0.815  0.41541    
## Ospedaleosp3         28.517     13.499   2.113  0.03474 *  
## SessoM               77.645     11.185   6.942 4.91e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 274 on 2488 degrees of freedom
## Multiple R-squared:  0.7288, Adjusted R-squared:  0.7279 
## F-statistic: 743.1 on 9 and 2488 DF,  p-value: < 2.2e-16
# Controllo la multicollinearità
car::vif(mod_finale)
##                  GVIF Df GVIF^(1/(2*Df))
## N.gravidanze 1.027985  1        1.013896
## Fumatrici    1.007363  1        1.003675
## Gestazione   1.677351  1        1.295126
## Lunghezza    2.086862  1        1.444597
## Cranio       1.626789  1        1.275456
## Tipo.parto   1.004213  1        1.002104
## Ospedale     1.003460  2        1.000864
## Sesso        1.040653  1        1.020124

Interpretazione dei risultati

Il modello selezionato mantiene un R² aggiustato di 0,728 e un errore standard residuo di circa 274 g.

Il controllo della multicollinearità non mostra problemi particolari: tutti i valori risultano contenuti.

I predittori possono quindi essere mantenuti nel modello, che passerà ora ai controlli diagnostici.

4. Diagnostica del modello finale

4.1 Analisi grafica dei residui

Controllo i residui del modello per verificare se presentano andamenti particolari, se la loro variabilità è costante e se ci sono osservazioni potenzialmente influenti.

# Visualizzo i quattro grafici diagnostici
par(mfrow = c(2, 2))

plot(mod_finale)

par(mfrow = c(1, 1))

4.2 Test sui residui

Dai grafici si notano alcune anomalie, soprattutto nella distribuzione dei residui. Utilizzo alcuni test statistici per controllare meglio il modello.

# Test di Breusch-Pagan per la varianza costante
lmtest::bptest(mod_finale)
## 
##  studentized Breusch-Pagan test
## 
## data:  mod_finale
## BP = 91.153, df = 9, p-value = 9.554e-16
# Test di Durbin-Watson per l'autocorrelazione
lmtest::dwtest(mod_finale)
## 
##  Durbin-Watson test
## 
## data:  mod_finale
## DW = 1.9529, p-value = 0.1197
## alternative hypothesis: true autocorrelation is greater than 0
# Test di Shapiro-Wilk per la normalità
shapiro.test(residuals(mod_finale))
## 
##  Shapiro-Wilk normality test
## 
## data:  residuals(mod_finale)
## W = 0.97415, p-value < 2.2e-16
# Grafico della distribuzione dei residui
plot(density(residuals(mod_finale)),
     main = "Distribuzione dei residui",
     xlab = "Residui (g)",
     col = "blue")

Interpretazione dei risultati

Il test di Breusch-Pagan è significativo (p < 0,001), quindi la variabilità dei residui non sembra costante.

Anche il test di Shapiro-Wilk è significativo (p < 0,001), indicando che i residui non seguono perfettamente una distribuzione normale. Il grafico mostra infatti una coda destra più lunga.

Il test di Durbin-Watson non evidenzia autocorrelazione significativa (p = 0,120), anche se il risultato dipende dall’ordine dei dati.

Il modello rimane utile, ma questi problemi rendono necessario interpretare con cautela i risultati statistici e le previsioni.

4.3 Individuazione delle osservazioni influenti

Controllo se alcune osservazioni hanno valori particolarmente diversi dalle altre e potrebbero influenzare le stime del modello.

Utilizzo i residui studentizzati, i valori di leverage e la distanza di Cook.

# Calcolo gli indicatori
lev <- hatvalues(mod_finale)
res_student <- rstudent(mod_finale)
cook <- cooks.distance(mod_finale)

# Soglie indicative
n <- nobs(mod_finale)
p <- length(coef(mod_finale))

soglia_lev <- 2 * p / n
soglia_cook <- 4 / n

# Grafici
par(mfrow = c(1, 3))

plot(lev, main = "Leverage",
     ylab = "Leverage", pch = 20)
abline(h = soglia_lev, col = "red")

plot(res_student, main = "Residui studentizzati",
     ylab = "Residui", pch = 20)
abline(h = c(-3, 3), col = "red")

plot(cook, main = "Distanza di Cook",
     ylab = "Cook", pch = 20)
abline(h = soglia_cook, col = "red")

par(mfrow = c(1, 1))

# Numero di osservazioni oltre le soglie
data.frame(
  Indicatore = c("Leverage", "Residui", "Cook"),
  Osservazioni = c(
    sum(lev > soglia_lev),
    sum(abs(res_student) > 3),
    sum(cook > soglia_cook)
  )
)
##   Indicatore Osservazioni
## 1   Leverage          184
## 2    Residui           22
## 3       Cook          128
# Mostro le 5 osservazioni con Cook maggiore
influenti <- order(cook, decreasing = TRUE)[1:5]

data.frame(
  Riga_originale = as.integer(rownames(model.frame(mod_finale)))[influenti],
  Cook = round(cook[influenti], 4),
  Leverage = round(lev[influenti], 4),
  Residuo = round(res_student[influenti], 2)
)
##      Riga_originale   Cook Leverage Residuo
## 1551           1551 0.5000   0.0495    9.99
## 310             310 0.0445   0.0297   -3.82
## 1920           1920 0.0260   0.0159    4.02
## 155             155 0.0205   0.0081    5.04
## 1780           1780 0.0193   0.0265    2.67

Interpretazione dei risultati

Il controllo individua 184 osservazioni con leverage elevato, 22 con residui studentizzati oltre ±3 e 128 sopra la soglia indicativa della distanza di Cook.

L’osservazione 1551 è quella più influente, con una distanza di Cook di 0,500 e un residuo studentizzato di circa 10.

Questi valori non indicano necessariamente errori. Prima di escludere eventuali osservazioni, verifico quanto influenzano i risultati del modello.

4.4 Verifica delle osservazioni influenti

Per capire quanto l’osservazione 1551 influisce sul modello, provo a stimarlo nuovamente senza questo caso e confronto i coefficienti.

L’esclusione viene utilizzata soltanto come controllo, senza modificare il dataset originale.

# Controllo l'osservazione più influente
dati_puliti[1551, ]
##      Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio
## 1551         35            1        No         38 4370      31.5   37.4
##      Tipo.parto Ospedale Sesso
## 1551   Naturale     osp3     F
# Creo un modello senza l'osservazione 1551
mod_senza_1551 <- update(
  mod_finale,
  subset = rownames(dati_confronto) != "1551"
)

# Confronto i coefficienti
confronto_coefficienti <- data.frame(
  Variabile = names(coef(mod_finale)),
  Originale = round(coef(mod_finale), 2),
  Senza_1551 = round(coef(mod_senza_1551), 2)
)

confronto_coefficienti$Differenza <- round(
  confronto_coefficienti$Senza_1551 -
    confronto_coefficienti$Originale, 2
)

print(confronto_coefficienti, row.names = FALSE)
##          Variabile Originale Senza_1551 Differenza
##        (Intercept)  -6678.95   -6680.23      -1.28
##       N.gravidanze     12.58      13.26       0.68
##        FumatriciSi    -30.43     -27.45       2.98
##         Gestazione     32.30      29.57      -2.73
##          Lunghezza    102.92     109.31       6.39
##             Cranio    104.87      98.72      -6.15
##  Tipo.partoCesareo    -29.67     -29.54       0.13
##       Ospedaleosp2    -10.95     -11.63      -0.68
##       Ospedaleosp3     28.52      25.34      -3.18
##             SessoM     77.65      77.81       0.16
# Confronto l'adattamento
data.frame(
  Modello = c("Originale", "Senza osservazione 1551"),
  R2_aggiustato = c(
    summary(mod_finale)$adj.r.squared,
    summary(mod_senza_1551)$adj.r.squared
  ),
  Errore_residuo = c(
    sigma(mod_finale),
    sigma(mod_senza_1551)
  )
)
##                   Modello R2_aggiustato Errore_residuo
## 1               Originale     0.7278667       273.9933
## 2 Senza osservazione 1551     0.7379105       268.7130

Interpretazione dei risultati

L’osservazione 1551 presenta un peso di 4.370 g e una lunghezza di 31,5 cm, una combinazione piuttosto insolita che potrebbe indicare un errore nei dati.

Escludendo temporaneamente questa osservazione, l’R² aggiustato passa da 0,7279 a 0,7379 e l’errore residuo diminuisce da 273,99 a 268,71 g.

Anche i coefficienti cambiano molto poco. Il modello sembra quindi abbastanza stabile rispetto a questa singola osservazione.

Per prudenza mantengo il caso nel dataset, segnalando comunque la possibile anomalia.

5. Previsione del peso alla nascita

5.1 Previsione per un caso specifico

Utilizzo il modello selezionato per stimare il peso di una neonata alla 39ª settimana di gestazione, con madre alla terza gravidanza.

Per le informazioni non specificate utilizzo valori medi del campione e categorie di riferimento. La previsione è quindi un esempio e non una stima clinica personalizzata.

# Creo il caso da prevedere
nuovo_caso <- data.frame(
  N.gravidanze = 2,
  Fumatrici = factor("No", levels = levels(dati_puliti$Fumatrici)),
  Gestazione = 39,
  Lunghezza = mean(dati_puliti$Lunghezza),
  Cranio = mean(dati_puliti$Cranio),
  Tipo.parto = factor("Naturale", levels = levels(dati_puliti$Tipo.parto)),
  Ospedale = factor("osp1", levels = levels(dati_puliti$Ospedale)),
  Sesso = factor("F", levels = levels(dati_puliti$Sesso))
)

# Mostro le caratteristiche utilizzate
nuovo_caso
##   N.gravidanze Fumatrici Gestazione Lunghezza   Cranio Tipo.parto Ospedale
## 1            2        No         39   49.4692 34.00292   Naturale     osp1
##   Sesso
## 1     F
# Previsione con intervallo al 95%
previsione <- predict(mod_finale,
                      newdata = nuovo_caso,
                      interval = "prediction",
                      level = 0.95)

round(previsione, 1)
##      fit    lwr    upr
## 1 3263.1 2725.2 3800.9

Interpretazione dei risultati

Per il caso considerato, il modello prevede un peso alla nascita di circa 3.263 g.

L’intervallo di previsione al 95% va da circa 2.725 a 3.801 g. Questo intervallo indica che il peso effettivo della neonata potrebbe essere anche abbastanza diverso dalla stima centrale.

Il risultato è stato ottenuto assumendo che la madre non fumi, che il parto sia naturale e che avvenga nell’ospedale 1. Per lunghezza e diametro craniale sono state utilizzate le medie del campione.

La previsione è quindi indicativa e deve essere interpretata con cautela, anche considerando i problemi emersi nella diagnostica del modello.

Un limite importante riguarda le misure utilizzate per la previsione. Anche se lunghezza e diametro craniale possono essere stimati durante la gravidanza tramite ecografia, non sappiamo se i valori presenti nel dataset siano stati rilevati prima o dopo il parto.

Anche il tipo di parto potrebbe non essere noto in anticipo. Per questo motivo, il risultato deve essere considerato una simulazione indicativa e non una previsione clinica già utilizzabile durante la gravidanza.

6. Visualizzazioni per il personale clinico

6.1 Peso previsto, gestazione e fumo materno

Per rendere più chiari i risultati del modello, rappresento il peso previsto in base alle settimane di gestazione, distinguendo le madri fumatrici dalle non fumatrici.

Per le altre variabili utilizzo valori medi e categorie di riferimento.

# Creo i dati per le previsioni
nuovi_dati <- expand.grid(
  N.gravidanze = 2,
  Fumatrici = levels(dati_puliti$Fumatrici),
  Gestazione = 25:43,
  Lunghezza = mean(dati_puliti$Lunghezza),
  Cranio = mean(dati_puliti$Cranio),
  Tipo.parto = "Naturale",
  Ospedale = "osp1",
  Sesso = "F"
)

# Imposto le categorie
nuovi_dati$Fumatrici <- factor(nuovi_dati$Fumatrici,
                              levels = levels(dati_puliti$Fumatrici))
nuovi_dati$Tipo.parto <- factor(nuovi_dati$Tipo.parto,
                               levels = levels(dati_puliti$Tipo.parto))
nuovi_dati$Ospedale <- factor(nuovi_dati$Ospedale,
                             levels = levels(dati_puliti$Ospedale))
nuovi_dati$Sesso <- factor(nuovi_dati$Sesso,
                          levels = levels(dati_puliti$Sesso))

# Calcolo il peso previsto
nuovi_dati$Peso_previsto <- predict(mod_finale,
                                    newdata = nuovi_dati)

# Grafico
library(ggplot2)

ggplot(nuovi_dati,
       aes(x = Gestazione, y = Peso_previsto,
           color = Fumatrici)) +
  geom_line(linewidth = 1.2) +
  labs(
    title = "Peso previsto e settimane di gestazione",
    x = "Settimane di gestazione",
    y = "Peso previsto (g)",
    color = "Madre fumatrice"
  ) +
  theme_minimal()

Interpretazione dei risultati

Il grafico mostra che il peso previsto aumenta di circa 32 g per ogni settimana aggiuntiva di gestazione, mantenendo costanti le altre caratteristiche.

Le madri fumatrici presentano un peso stimato inferiore di circa 30 g rispetto alle non fumatrici. Questa differenza, però, non è statisticamente significativa (p = 0,269).

Le due linee sono parallele perché il modello non prevede un’interazione tra fumo e gestazione.

Le previsioni sono indicative e vanno interpretate con cautela, soprattutto per le gestazioni molto premature.

6.2 Peso previsto e misure antropometriche

Rappresento il peso previsto in relazione alla lunghezza e al diametro craniale, che risultano tra le variabili maggiormente associate al peso alla nascita.

# Creo i dati per i grafici
dati_grafici <- data.frame(
  N.gravidanze = 2,
  Fumatrici = factor("No", levels = levels(dati_puliti$Fumatrici)),
  Gestazione = 39,
  Lunghezza = seq(45, 55, length.out = 100),
  Cranio = mean(dati_puliti$Cranio),
  Tipo.parto = factor("Naturale", levels = levels(dati_puliti$Tipo.parto)),
  Ospedale = factor("osp1", levels = levels(dati_puliti$Ospedale)),
  Sesso = factor("F", levels = levels(dati_puliti$Sesso))
)

# Previsione in base alla lunghezza
dati_grafici$Peso_previsto <- predict(mod_finale,
                                      newdata = dati_grafici)

grafico_lunghezza <- ggplot(dati_grafici,
                           aes(x = Lunghezza, y = Peso_previsto)) +
  geom_line(color = "steelblue", linewidth = 1.2) +
  labs(title = "Peso previsto e lunghezza",
       x = "Lunghezza (cm)",
       y = "Peso previsto (g)") +
  theme_minimal()

# Modifico i dati per il diametro craniale
dati_grafici$Lunghezza <- mean(dati_puliti$Lunghezza)
dati_grafici$Cranio <- seq(30, 38, length.out = 100)

dati_grafici$Peso_previsto <- predict(mod_finale,
                                      newdata = dati_grafici)

grafico_cranio <- ggplot(dati_grafici,
                        aes(x = Cranio, y = Peso_previsto)) +
  geom_line(color = "darkgreen", linewidth = 1.2) +
  labs(title = "Peso previsto e diametro craniale",
       x = "Diametro craniale (cm)",
       y = "Peso previsto (g)") +
  theme_minimal()

# Mostro i grafici
print(grafico_lunghezza)

print(grafico_cranio)

Interpretazione dei risultati

I grafici mostrano una relazione positiva tra il peso previsto e le misure antropometriche.

Secondo il modello, a parità delle altre caratteristiche, ogni centimetro aggiuntivo di lunghezza è associato a circa 103 g in più, mentre ogni centimetro aggiuntivo di diametro craniale è associato a circa 105 g in più.

Entrambe le relazioni risultano statisticamente significative (p < 0,001).

Questi risultati confermano che lunghezza e diametro craniale sono importanti per stimare il peso alla nascita, anche se da soli non permettono una previsione precisa.

7. Conclusioni

L’analisi delle 2.500 nascite ha permesso di studiare le principali caratteristiche dei neonati e di costruire un modello per stimare il peso alla nascita.

I test statistici non hanno evidenziato differenze significative nella frequenza dei parti cesarei tra i tre ospedali.

Il peso medio del campione è risultato compatibile con il riferimento italiano di 3.300 g, mentre la lunghezza media è leggermente inferiore ai 50 cm di riferimento. Sono emerse anche differenze significative tra maschi e femmine per peso, lunghezza e diametro craniale.

Il modello finale spiega circa il 73% della variabilità del peso. Le variabili maggiormente associate al peso sono la lunghezza, il diametro craniale e le settimane di gestazione.

Per il caso richiesto, il peso previsto è di circa 3.263 g, con un intervallo di previsione al 95% compreso tra 2.725 e 3.801 g.

Il modello presenta però alcuni limiti. I residui non rispettano completamente le ipotesi di normalità e varianza costante, quindi i risultati vanno interpretati con cautela. Inoltre, alcune osservazioni sono potenzialmente anomale.

Un altro limite riguarda la disponibilità delle informazioni: per utilizzare il modello durante la gravidanza è necessario disporre di misure prenatali affidabili. Non tutte le informazioni utilizzate potrebbero essere disponibili prima del parto.

Nel complesso, il modello può essere utile per comprendere le relazioni tra le variabili e fornire stime indicative, ma non dovrebbe essere utilizzato da solo per prendere decisioni cliniche.