gini.index = function(x) {
ni = table(x)
fi = ni/length(x)
fi2 = fi^2
J = length(table(x))
gini = 1-sum(fi2)
gini.normalizzato = gini/((J-1)/J)
}
Per costruire il modello predittivo, abbiamo raccolto dati su 2500 neonati provenienti da tre ospedali. Le variabili raccolte includono:
Età della madre: Misura dell’età in anni -> variabile quantitativa
discreta.
Numero di gravidanze: Quante gravidanze ha avuto la madre
-> variabile quantitativa discreta.
Fumo materno: Un indicatore
binario (0=non fumatrice, 1=fumatrice) -> variabile qualitativa
dicotomica su scala nominale.
Durata della gravidanza: Numero di
settimane di gestazione -> variabile quantitativa discreta.
Peso
del neonato: Peso alla nascita in grammi -> variabile quantitativa
continua.
Lunghezza e diametro del cranio: Lunghezza del neonato e
diametro craniale, misurabili anche durante la gravidanza tramite
ecografie -> variabili quantitative continue.
Tipo di parto:
Naturale o cesareo -> variabile qualitativa su scala nominale.
Ospedale di nascita: Ospedale 1, 2 o 3 -> variabile qualitativa su
scala nominale.
Sesso del neonato: Maschio (M) o femmina (F) ->
variabile qualitativa dicotomica su scala nominale.
L’obiettivo principale è identificare quali di queste variabili sono più predittive del peso alla nascita, con un focus particolare sull’impatto del fumo materno e delle settimane di gestazione, che potrebbero indicare nascite premature.
Iniziamo importando il dataset e mostrando le prime 5 osservazioni:
dati <- read.csv("neonati.csv", stringsAsFactors = T)
attach(dati)
knitr::kable((head(dati,5)), "pipe")
| Anni.madre | N.gravidanze | Fumatrici | Gestazione | Peso | Lunghezza | Cranio | Tipo.parto | Ospedale | Sesso |
|---|---|---|---|---|---|---|---|---|---|
| 26 | 0 | 0 | 42 | 3380 | 490 | 325 | Nat | osp3 | M |
| 21 | 2 | 0 | 39 | 3150 | 490 | 345 | Nat | osp1 | F |
| 34 | 3 | 0 | 38 | 3640 | 500 | 375 | Nat | osp2 | M |
| 28 | 1 | 0 | 41 | 3690 | 515 | 365 | Nat | osp2 | M |
| 20 | 0 | 0 | 38 | 3700 | 480 | 335 | Nat | osp3 | F |
Nella prima fase, esploreremo le variabili attraverso un’analisi descrittiva per comprenderne la distribuzione e identificare eventuali outlier o anomalie. Un focus particolare sarà dato alla relazione tra le variabili materne (età, fumo, gravidanze precedenti) e il peso del neonato.
Analizziamo le variabili singolarmente.
Usiamo il pacchetto psych per avere una overview più completa dei dati:
knitr::kable(psych::describe(Anni.madre))
| vars | n | mean | sd | median | trimmed | mad | min | max | range | skew | kurtosis | se | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| X1 | 1 | 2500 | 28.164 | 5.273578 | 28 | 28.102 | 4.4478 | 0 | 46 | 46 | 0.0427858 | 0.3777127 | 0.1054716 |
Da una prima analisi risulta che alcune osservazioni contengono degli
errori di raccolta dati, infatti, sono presenti i valori:
* 0 ->
osservazione numero 1380.
* 1 -> osservazione numero 1152.
which(Anni.madre == 0)
## [1] 1380
which(Anni.madre == 1)
## [1] 1152
Dopo esserci assicurati che questi sono gli unici valori errati
presenti per questa variabile possiamo proseguire in due modi:
*
eliminare le osservazioni
* sostituire Anni.madre[1380] e
Anni.madre[1152] con il valore della mediana, ovvero 28 (fonte: https://labdisia.disia.unifi.it/gmm/eco/lez/sett2.pdf).
Proseguiamo con la seconda strada:
Anni.madre[1380] <- median(Anni.madre)
Anni.madre[1152] <- median(Anni.madre)
knitr::kable(psych::describe(Anni.madre))
| vars | n | mean | sd | median | trimmed | mad | min | max | range | skew | kurtosis | se | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| X1 | 1 | 2500 | 28.186 | 5.215121 | 28 | 28.1085 | 4.4478 | 13 | 46 | 33 | 0.1511176 | -0.1055943 | 0.1043024 |
Dai dati mostrati sopra vediamo che la variabile Anni.madre ha un valore minimo di 13 e massimo di 46, con un valor medio di 28.18 e mediana pari a 28. La piccola differenza tra media e mediana è confermata dal piccolo coefficiente di skewness (0.15), che indica una leggera asimmetria positiva (valori bassi più frequenti). L’indice di curtosi è negativo (-0.10), indicando una forma platicurtica. Il coefficiente di variazione è pari al 18.48%.
boxplot(Anni.madre, col = "orange",
main = "Boxplot Anni.madre")
plot(density(Anni.madre), col = 1,
main = "Distribuzione Anni.madre",
xlab = "Anni madre",
ylab = "Densità di probabilita")
abline(v = mean(Anni.madre), col = 2)
abline(v = median(Anni.madre), col = 3)
abline(h=c(0, 0.02, 0.04, 0.06), col="grey10", lty="dotted")
abline(v=c(10, 20, 30, 40, 50), col="grey10", lty="dotted")
knitr::kable(psych::describe(N.gravidanze))
| vars | n | mean | sd | median | trimmed | mad | min | max | range | skew | kurtosis | se | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| X1 | 1 | 2500 | 0.9812 | 1.280587 | 1 | 0.745 | 1.4826 | 0 | 12 | 12 | 2.512746 | 10.97822 | 0.0256117 |
Il summary mostra che il valor medio del numero di gravidanze è 1, con valori minimi di zero (quindi nessuna gravidanza precedente) e un valore massimo di 12. L’indice di skewness è pari a 2.51, indicando una simmetria positiva, il che significa che un numero basso di gravidanze è più frequente. Il coefficiente di curtosi positivo (10.97) indica un andamento leptocurtico, con valori centrali più probabili rispetto alle code. Trattandosi di una variabile discreta, possiamo vedere un grafico a barre che mostra la distribuzione del numero di gravidanze nel dataset, che mostra come il dato più frequente è zero, con 1096 donne che non hanno mai avuto una gravidanza.
my_bar <- barplot(height=table(N.gravidanze),
col = "orange",
main = "Distribuzione N.gravidanze",
xlab = "Numero di gravidanze precedenti",
ylab = "Frequenza assoluta",
ylim=c(0, 1200))
text(my_bar, table(N.gravidanze)+ 45, paste(table(N.gravidanze), sep="") ,cex=1)
knitr::kable(psych::describe(Gestazione))
| vars | n | mean | sd | median | trimmed | mad | min | max | range | skew | kurtosis | se | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| X1 | 1 | 2500 | 38.9804 | 1.868639 | 39 | 39.185 | 1.4826 | 25 | 43 | 18 | -2.064074 | 8.249145 | 0.0373728 |
Il valore medio della variabile gestazione è 38.98 settimane (corrsipondente a 272 giorni, 9 mesi) e il valore mediano 39. Il coefficente di skewness è pari a -2.06, indicando un’asimmetria negativa (valori alti maggiormente frequenti); l’indice di curtosi è positivo (8.24), che indica un andamento leptocurtico.
boxplot(Gestazione, col = "orange",
main = "Boxplot settimane di Gestazione")
my_bar <- barplot(height=table(Gestazione),
col = "orange",
main = "Distribuzione Gestazione",
xlab = "Settimane di gestazione",
ylab = "Frequenza assoluta",
ylim=c(0, 1200),
las = 2)
text(my_bar, table(Gestazione)+ 45, paste(table(Gestazione), sep="") ,cex=1)
knitr::kable(psych::describe(Peso))
| vars | n | mean | sd | median | trimmed | mad | min | max | range | skew | kurtosis | se | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| X1 | 1 | 2500 | 3284.081 | 525.0387 | 3300 | 3302.901 | 459.606 | 830 | 4930 | 4100 | -0.6466427 | 2.027507 | 10.50077 |
Il valore medio è 3284 grammi, il minimo 830 e il massimo 4930. La skewness è 10.50 (asimmetria positiva, con valori inferiori più probabili) e curtosi positiva (2.02, andamento leptocurtico). La deviazione standard è 525 g, che corrisponde a un coefficiente di variazione del 15%.
plot(density(Peso), col = 1,
main = "Distribuzione Peso",
xlab = "Peso [g]",
ylab = "Densità di probabilita")
abline(v = mean(Peso), col = 2)
abline(v = median(Peso), col = 3)
abline(h=c(0, 4e-4, 8e-4), col="grey10", lty="dotted")
abline(v=c(1000, 2000, 3000, 4000, 5000), col="grey10", lty="dotted")
boxplot(Peso, col = "orange",
main = "Boxplot Peso")
knitr::kable(psych::describe(Lunghezza))
| vars | n | mean | sd | median | trimmed | mad | min | max | range | skew | kurtosis | se | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| X1 | 1 | 2500 | 494.692 | 26.31864 | 500 | 496.45 | 22.239 | 310 | 565 | 255 | -1.51379 | 6.479586 | 0.5263729 |
Il valore medio della lunghezza è 494 mm con una mediana di 500 mm. Il valori minimo e massimo sono rispettivamente 310 e 565 mm. La skewness è negativa (-1.5, valori maggiori più probabili) e la forma leptocurtica (indice di curtosi uguale a 6.48). la deviazione standard è 26.31 mm, che corrisponde a un coefficiente di variazione del 6%.
plot(density(Lunghezza), col = 1,
main = "Distribuzione Lunghezza",
xlab = "Lunghezza [mm]",
ylab = "Densità di probabilita")
abline(v = mean(Lunghezza), col = 2)
abline(v = median(Lunghezza), col = 3)
abline(h=c(0.005, 0.01, 0.015, 0.02), col="grey10", lty="dotted")
abline(v=c(300, 350, 400, 450, 500, 550), col="grey10", lty="dotted")
knitr::kable(psych::describe(Cranio))
| vars | n | mean | sd | median | trimmed | mad | min | max | range | skew | kurtosis | se | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| X1 | 1 | 2500 | 340.0292 | 16.42533 | 340 | 340.6845 | 14.826 | 235 | 390 | 155 | -0.7845817 | 2.94145 | 0.3285066 |
La variabile cranio ha un valore medio uguale alla mediana, 340 mm. I valori minimo e massimo sono rispettivamente 235 e 390 mm. Ha un’asimmetria leggermente negativa (skewness pari a -0.78) e an andamento leptocurtico (indice di curtosi uguale a 2.94). La deviazione standard è 16.42, che corrisponde a un coefficiente di variazione del 4.7 %.
plot(density(Cranio), col = 1,
main = "Distribuzione Diametro cranio",
xlab = "Diametro Cranio [mm]",
ylab = "Densità di probabilita")
abline(v = mean(Cranio), col = 2)
abline(v = median(Cranio), col = 3)
abline(h=c(0, 0.01, 0.02), col="grey10", lty="dotted")
abline(v=c(250, 300, 350, 400), col="grey10", lty="dotted")
Fumatrici_ni = table(Fumatrici)
Fumatrici_fi = Fumatrici_ni/length(Fumatrici)
Fumatrici_distr = cbind(Fumatrici_ni, Fumatrici_fi)
knitr::kable(Fumatrici_distr, "pipe")
| Fumatrici_ni | Fumatrici_fi | |
|---|---|---|
| 0 | 2396 | 0.9584 |
| 1 | 104 | 0.0416 |
print(gini.index(Fumatrici))
## [1] 0.1594778
my_bar <- barplot(height=table(Fumatrici),
col = "orange",
main = "Frequenze assolute Fumatrici",
xlab = "",
ylab = "Frequenza assoluta",
ylim=c(0, 3000))
text(my_bar, table(Fumatrici)+ 100, paste(table(Fumatrici), sep=" ") ,cex=1)
Il numero di non fumatrici è 23 volte più alto rispetto alla fumatrici, che rappresentano solo il 4.1 % del campione. L’indice di Gini è pari a 0.16 (scarsa eterogeneità).
Tipo.parto_ni = table(Tipo.parto)
Tipo.parto_fi = Tipo.parto_ni/length(Tipo.parto)
Tipo.parto_distr = cbind(Tipo.parto_ni, Tipo.parto_fi)
knitr::kable(Tipo.parto_distr, "pipe")
| Tipo.parto_ni | Tipo.parto_fi | |
|---|---|---|
| Ces | 728 | 0.2912 |
| Nat | 1772 | 0.7088 |
print(gini.index(Tipo.parto))
## [1] 0.8256102
my_bar <- barplot(height=table(Tipo.parto),
col = "orange",
main = "Frequenze assolute Tipo.parto",
xlab = "Tipo parto (cesareo/naturale)",
ylab = "Frequenza assoluta",
ylim=c(0, 2500))
text(my_bar, table(Tipo.parto)+ 100, paste(table(Tipo.parto), sep=" ") ,cex=1)
Il numero di parti naturali è 2.4 volte il numero ci parti cesarei, che rappresentano il 29% del campione. L’indice di Gini è 0.82.
Ospedale_ni = table(Ospedale)
Ospedale_fi = Ospedale_ni/length(Ospedale)
Ospedale_distr = cbind(Ospedale_ni, Ospedale_fi)
knitr::kable(Ospedale_distr, "pipe")
| Ospedale_ni | Ospedale_fi | |
|---|---|---|
| osp1 | 816 | 0.3264 |
| osp2 | 849 | 0.3396 |
| osp3 | 835 | 0.3340 |
print(gini.index(Ospedale))
## [1] 0.9998683
my_bar <- barplot(height=table(Ospedale),
col = "orange",
main = "Frequenze assolute per ogni ospedale",
xlab = "Ospedale",
ylab = "Frequenza assoluta",
ylim=c(0, 1000))
text(my_bar, table(Ospedale)+ 100, paste(table(Ospedale), sep=" ") ,cex=1)
Le osservazioni sono distribuite in maniera molto equa tra le 3 modalità, con un indice di Gini di 0.9998, indicando massima eterogeneità.
Sesso_ni = table(Sesso)
Sesso_fi = Sesso_ni/length(Sesso)
Sesso_distr = cbind(Sesso_ni, Sesso_fi)
knitr::kable(Sesso_distr, "pipe")
| Sesso_ni | Sesso_fi | |
|---|---|---|
| F | 1256 | 0.5024 |
| M | 1244 | 0.4976 |
print(gini.index(Sesso))
## [1] 0.999977
my_bar <- barplot(height=table(Sesso),
col = "orange",
main = "Frequenze assolute Sesso",
xlab = "Sesso (M/F)",
ylab = "Frequenza assoluta",
ylim=c(0, 1500))
text(my_bar, table(Sesso)+ 100, paste(table(Sesso), sep=" ") ,cex=1)
La variabile sesso è distribuita equamente tra M e F, con un indice di Gini di 1 (massima eterogeità).
Facciamo un’analisi multidimensionale della variabile Peso in relazione alle altre variabili materne (età, fumo, gravidanze precedenti). Mostriamo i boxplot, gli scatterplot e calcoliamo dei summary con il pacchetto dplyr.
dati$Anni.madre_CL <- cut(Anni.madre, breaks = c (12, 24, 35, 46))
knitr::kable(table(dati$Anni.madre_CL), "pipe")
| Var1 | Freq |
|---|---|
| (12,24] | 595 |
| (24,35] | 1687 |
| (35,46] | 218 |
boxplot(Peso~dati$Anni.madre_CL, ,
col = "orange",
main = "Boxplot Peso~Anni.madre",
xlab = "Classi di età Anni.madre")
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
dati %>%
group_by(Anni.madre_CL) %>%
summarize(media = mean(Peso), devstd = sd(Peso))
## # A tibble: 3 × 3
## Anni.madre_CL media devstd
## <fct> <dbl> <dbl>
## 1 (12,24] 3277. 469.
## 2 (24,35] 3294. 526.
## 3 (35,46] 3223. 645.
Dal boxplot e dal summary si vede che il valor medio della variabile peso per la fascia di età (35,46] subisce un leggero calo (di 54 g e 71 g rispetto alle classi (12,24] e (24,35]); l’aspetto di maggior rilievo è tuttavia l’aumento della deviazione standard; passiamo infatti da un coefficiente di variazione del 14% per la classe (12,24], al 15.9% della classe di età (24,35], per finire al 19.98% per ultima classe di età.
plot(Peso~jitter(Anni.madre,3), pch = 1, cex = 0.5, col = "purple")
cor(Peso, Anni.madre)
## [1] -0.02377346
Dallo scatterplot si vede un andamento orizzontale, confermato dal basso coefficiente di correlazione -0.023.
boxplot(Peso~Fumatrici,
col = "orange",
main = "Boxplot Peso~Fumatrici",
xlab = "Fumatrici (SI/NO)")
dati %>%
group_by(Fumatrici) %>%
summarize(media = mean(Peso), devstd = sd(Peso))
## # A tibble: 2 × 3
## Fumatrici media devstd
## <int> <dbl> <dbl>
## 1 0 3286. 527.
## 2 1 3236. 479.
Nella classificazione della variabile peso in base alla variabile dicotomica Fumatrici, possiamo notare una diminuzione del peso medio da 3286 g a 3236, corrispondente a una diminuzione percentuale dell’ 1.5 % passando da “non-fumatrici” a “fumatrici” e una diminuzione del coefficiente di variazione che passa dal 16% al 14.7%.
boxplot(Peso~dati$N.gravidanze, ,
col = "orange",
main = "Boxplot Peso~N.gravidanze",
xlab = "Numero di gravidanze precedenti")
Peso_N.gravidanze <- dati %>%
group_by(N.gravidanze) %>%
summarize(media = mean(Peso), devstd = sd(Peso))
Peso_N.gravidanze
## # A tibble: 13 × 3
## N.gravidanze media devstd
## <int> <dbl> <dbl>
## 1 0 3279. 519.
## 2 1 3275. 510.
## 3 2 3319. 504.
## 4 3 3289. 595.
## 5 4 3398. 685.
## 6 5 3316. 446.
## 7 6 3063. 829.
## 8 7 2220 NA
## 9 8 3076. 944.
## 10 9 3455 431.
## 11 10 2973. 107.
## 12 11 3400 NA
## 13 12 3350 NA
y1 <- as.data.frame(t(Peso_N.gravidanze[2]))
x1 <- seq(0,12,1)
plot(x1, y1, ylim=c(1000, 3500))
lines(x1, y1, col = "red")
Considerato che i dati del campione per i quali il numero di gravidanze è superiore a 3 è molto ridotto, non è possibile individuare in questo momento un trend chiaro che leghi la variabile peso al numero di gravidanze precedenti.
plot(Peso~jitter(N.gravidanze,3), pch = 1, cex = 0.5, col = "purple")
cor(Peso, N.gravidanze)
## [1] 0.0024073
La nuvola di punti è molto addensata nella regione 0-1, quella in cui ci sono la maggior parte delle nascite; tuttavia graficamente non è possibile individuare un trend chiaro, confermato dal coefficiente di correlazione (0.002).
Verrà sviluppato un modello di regressione lineare multipla che includa tutte le variabili rilevanti. In questo modo, potremo quantificare l’impatto di ciascuna variabile indipendente sul peso del neonato. Ad esempio, ci aspettiamo che il fumo materno e le gravidanze multiple abbiano effetti negativi sul peso alla nascita, mentre una maggiore durata della gestazione potrebbe aumentare il peso del neonato.
Con la funzione pairs, mostriamo la matrice delle correlazioni. Creiamo un nuovo dataframe per vedere la matrice delle correlazioni tra la variabile Peso e le altre variabili quantitative (Anni.madre, N,gravidanze, Gestazione, Lunghezza, Cranio).
?pairs
panel.cor <- function(x, y, digits = 2, prefix = "", cex.cor, ...)
{
par(usr = c(0, 1, 0, 1))
r <- abs(cor(x, y))
txt <- format(c(r, 0.123456789), digits = digits)[1]
txt <- paste0(prefix, txt)
if(missing(cex.cor)) cex.cor <- 0.8/strwidth(txt)
text(0.5, 0.5, txt, cex = 1.5)
}
library(dplyr)
dati_quant <- data.frame(Peso, Anni.madre, N.gravidanze, Gestazione, Lunghezza, Cranio)
pairs(dati_quant,lower.panel=panel.cor, upper.panel=panel.smooth)
Dalla matrice delle correlazioni possiamo fare queste
considerazioni:
- le variabili che mostrano il coefficiente di
correlazione maggiore con la variabile Peso sono:
1) Gestazione con
un coefficente di 0.59.
2) Lunghezza con correlazione positiva e
coefficiente 0.80.
3) Diametro del cranio con coefficiente di
correlazione 0.70.
- bisognerà verificare problemi di
multicollinearità calcolando i VIF, considerati i coefficenti di
correlzione tra:
1) Anni.Madre e N.Gravidanze.
2) Lunghezza e
Gestazione.
3) Lunghezza e Cranio.
4) Gestazione e
Cranio.
Per quanto riguarda le variabili qualitative (Fumatrici, Tipo.parto,
Ospedale e Sesso) vediamo i boxplot condizionati di Peso e della
variabile qualitativa.
Partendo dalla variabile Fumatrici:
par(mfrow = c(1,2))
boxplot(Peso, main = "Peso", col = "orange")
boxplot(Peso~Fumatrici, main = "Peso~Fumatrici", col = "orange")
Facciamo un t.test per saggiare l’ipotesi di uguaglianza delle medie tra gruppi indipendenti:
t.test(Peso~Fumatrici)
##
## Welch Two Sample t-test
##
## data: Peso by Fumatrici
## t = 1.034, df = 114.1, p-value = 0.3033
## alternative hypothesis: true difference in means between group 0 and group 1 is not equal to 0
## 95 percent confidence interval:
## -45.61354 145.22674
## sample estimates:
## mean in group 0 mean in group 1
## 3286.153 3236.346
Il p_value è 0.30, quindi siamo ampiamente nella zona di non rifiuto; pertanto non possiamo rifiutare l’ipotesi nulla H0 secondo la quale la differenza delle medie tra peso dei neonati da madri fumatrici e non fumatrici non è significativamente diversa da zero.
plot(density(rt(100000, 114.1)), main = "t test di differenza tra medie di Peso~Fumatrici")
abline(v = qt(0.025, 114), col = "red")
abline(v = qt(0.975, 114), col = "red")
points(x = 1.034, y = 0, col = "blue", pch = 20, cex = 3)
Inspettatamente la variabile Fumatrici non ha un’influenza significativa sul peso del neonato; tuttavia questo risultato potrebbe essere anche dovuto al fatto che il numero di madri fumatrici è pari a 104, ovvero al 4.16% del campione. In letteratura ci sono studi che smentiscono il t.test effettuato sui dati del campione (https://bmcpregnancychildbirth.biomedcentral.com/articles/10.1186/s12884-018-1694-4#:~:text=Compared%20with%20infants%20born%20to%20nonsmoking%20mothers%2C%20mean%20birth%20weight,cigarettes%20per%20day%20during%20pregnancy.).
count(dati, Fumatrici)
## Fumatrici n
## 1 0 2396
## 2 1 104
par(mfrow = c(1,2))
boxplot(Peso, main = "Peso", col = "orange")
boxplot(Peso~Tipo.parto, main = "Tipo.parto", col = "orange")
Ripetiamo anche in questo caso il t.test:
t.test(Peso~Tipo.parto)
##
## Welch Two Sample t-test
##
## data: Peso by Tipo.parto
## t = -0.12968, df = 1493, p-value = 0.8968
## alternative hypothesis: true difference in means between group Ces and group Nat is not equal to 0
## 95 percent confidence interval:
## -46.27992 40.54037
## sample estimates:
## mean in group Ces mean in group Nat
## 3282.047 3284.916
Anche in questo caso il p_value è molto alto e non possiamo rifiutare l’ipotesi nulla.
plot(density(rt(100000, 1493)), main = "t test di differenza tra medie di Peso~Tipo.parto")
abline(v = qt(0.025, 1493), col = "red")
abline(v = qt(0.975, 1493), col = "red")
points(x = -0.12968, y = 0, col = "blue", pch = 20, cex = 3)
par(mfrow = c(1,2))
boxplot(Peso, main = "Peso", col = "orange")
boxplot(Peso~Ospedale, main = "Ospedale", col = "orange")
In questi caso le modalità della variabile qualitative ospedale sono 3, quindi utilizzeremo un t.test per saggiare l’ipotesi di differenze tra medie di gruppi indipendenti della variabile peso utilizzando la correzione di Bonferroni:
pairwise.t.test(Peso, Ospedale, paired = F, pool.sd = T, p.adjust.methods = "bonferroni")
##
## Pairwise comparisons using t tests with pooled SD
##
## data: Peso and Ospedale
##
## osp1 osp2
## osp2 0.99 -
## osp3 0.33 0.33
##
## P value adjustment method: holm
In tutti e 3 i confronti incrociati, i p_value hanno valori molto alti e pertando non possiamo rifiutare l’ipotesi nulla H0: le differenze tra le medie della variabile peso non sono significativamente diverse da zero al variare dell’ospedale.
par(mfrow = c(1,2))
boxplot(Peso, main = "Peso", col = "orange")
boxplot(Peso~Sesso, main = "Sesso", col = "orange")
Facciamo anche in questo caso il t.test:
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
Il p_value è minimo (<2.2e-16), pertanto possiamo rifiutare l’ipotesi nulla H0 e dire che con la media del Peso del neonato è significativamente diversa a seconda del sesso.
plot(density(rt(100000, 2490.7)), main = "t test di differenza tra medie di Peso~Sesso", xlim = c(-20,4))
abline(v = qt(0.025, 2490.7), col = "red")
abline(v = qt(0.975, 2490.7), col = "red")
points(x = -12.106, y = 0, col = "blue", pch = 20, cex = 3)
Per la creazione del modello inseriamo inizialmente tutte le variabili, poi faremo un’analisi per semplificarlo:
mod1 <- lm(Peso~Anni.madre+N.gravidanze+Fumatrici+Gestazione+Lunghezza+Cranio+Tipo.parto+Ospedale+Sesso)
summary(mod1)
##
## Call:
## lm(formula = Peso ~ Anni.madre + N.gravidanze + Fumatrici + Gestazione +
## Lunghezza + Cranio + Tipo.parto + Ospedale + Sesso)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1123.3 -181.2 -14.6 160.7 2612.6
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6735.1677 141.3977 -47.633 < 2e-16 ***
## Anni.madre 0.7983 1.1463 0.696 0.4862
## N.gravidanze 11.4118 4.6665 2.445 0.0145 *
## Fumatrici -30.1567 27.5396 -1.095 0.2736
## Gestazione 32.5265 3.8179 8.520 < 2e-16 ***
## Lunghezza 10.2951 0.3007 34.237 < 2e-16 ***
## Cranio 10.4725 0.4261 24.580 < 2e-16 ***
## Tipo.partoNat 29.5027 12.0848 2.441 0.0147 *
## Ospedaleosp2 -11.2216 13.4388 -0.835 0.4038
## Ospedaleosp3 28.0984 13.4972 2.082 0.0375 *
## SessoM 77.5473 11.1779 6.938 5.07e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 273.9 on 2489 degrees of freedom
## Multiple R-squared: 0.7289, Adjusted R-squared: 0.7278
## F-statistic: 669.1 on 10 and 2489 DF, p-value: < 2.2e-16
Gestazione, Lunghezza e Cranio sono le variabili quantitative con i
coefficienti di regressione che hanno un peso maggiore all’interno del
modello e un p_value molto piccolo. Per quanto riguarda il tipo di
parto, si evidenzia che il parto naturale ha un coefficente di
regressione beta positivo (29.50) e un beta molto significativo
(0.0147). La variabile Sesso ha un p_value molto piccolo e assegna un
coefficiente beta di 77.55 nel caso il neonato sia di sesso
maschile.
La variabile Anni.madre ha un p_value molto alto che
suggerisce una scarsa influenza sul modello, così come le variabili
Fumatrici e Ospedale.
Il valore di R^2 adjusted è pari al 72%, ovvero un modello che spiega il 72% della varianza del campione.
Attraverso tecniche di selezione del modello, come la minimizzazione del criterio di informazione di Akaike (AIC) o di Bayes (BIC), selezioneremo il modello più parsimonioso, eliminando le variabili non significative. Verranno considerati anche modelli con interazioni tra le variabili e possibili effetti non lineari.
In questa fase proveremo a ottimizzare il modello, provando a semplificarlo, riducendo il numero di variabili e provando a massimizzare il coefficiente R^2.
Come primo step proviamo ad eliminare dal modello le variabili che riteniamo non significative.
mod2 <- update(mod1,~.-Ospedale-Fumatrici-Anni.madre)
summary(mod2)
##
## Call:
## lm(formula = Peso ~ N.gravidanze + Gestazione + Lunghezza + Cranio +
## Tipo.parto + Sesso)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1129.31 -181.70 -16.31 161.07 2638.85
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6707.2971 135.9911 -49.322 < 2e-16 ***
## N.gravidanze 12.7558 4.3366 2.941 0.0033 **
## Gestazione 32.2713 3.7941 8.506 < 2e-16 ***
## Lunghezza 10.2864 0.3007 34.207 < 2e-16 ***
## Cranio 10.5057 0.4260 24.659 < 2e-16 ***
## Tipo.partoNat 30.0342 12.0969 2.483 0.0131 *
## SessoM 77.9285 11.1905 6.964 4.22e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 274.3 on 2493 degrees of freedom
## Multiple R-squared: 0.7277, Adjusted R-squared: 0.727
## F-statistic: 1110 on 6 and 2493 DF, p-value: < 2.2e-16
Al modello 2 sono state sottratte 3 variabili (Anni.madre, Fumatrici e Ospedale); il nuovo modello ha un coefficiente R^2 simile al modello1 (72%) ma con 3 variabili in meno; per il criterio del rasoio di Occam questo modello è da considerarsi migliore rispetto al modello 1. I p_value sono cambiati significativamente (la variazione maggiore si osserva su N.gravidanze il cui p_value è passato da 0.014 del modello 1 a 0.0033 del modello 2).
Proviamo a semplificare ulteriormente eliminado la variabile N.gravidanze.
mod3 <- update(mod2,~.-N.gravidanze)
summary(mod3)
##
## Call:
## lm(formula = Peso ~ Gestazione + Lunghezza + Cranio + Tipo.parto +
## Sesso)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1118.43 -185.56 -16.07 161.53 2626.18
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6675.8084 135.7769 -49.167 < 2e-16 ***
## Gestazione 31.1917 3.7821 8.247 2.59e-16 ***
## Lunghezza 10.2412 0.3008 34.049 < 2e-16 ***
## Cranio 10.6397 0.4242 25.080 < 2e-16 ***
## Tipo.partoNat 29.1062 12.1113 2.403 0.0163 *
## SessoM 79.0670 11.2010 7.059 2.17e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 274.7 on 2494 degrees of freedom
## Multiple R-squared: 0.7267, Adjusted R-squared: 0.7262
## F-statistic: 1326 on 5 and 2494 DF, p-value: < 2.2e-16
Il modello 3 ha un coefficiente R^2 praticamente uguale al modello 2
ma con una variabile in meno. I p_value non sono cambiati in modo
significativo rispetto al caso precedente; pertanto a parità di
prestazioni, il modello 3 è attualmente da preferire.
Osservando in dettaglio gli scatterplot, si osserva una flessione della nuvola di punti nella curva Peso~Gestazione, che potrebbe essere sinonimo di una non-linearità. Proviamo ad inserire nel modello una dipendenza di tipo lineare e quadratica di Peso da Gestazione:
mod4 <- update(mod3, ~.+I(Gestazione^2))
summary(mod4)
##
## Call:
## lm(formula = Peso ~ Gestazione + Lunghezza + Cranio + Tipo.parto +
## Sesso + I(Gestazione^2))
##
## Residuals:
## Min 1Q Median 3Q Max
## -1120.27 -184.61 -15.21 164.47 2648.27
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -4704.6435 899.0411 -5.233 1.81e-07 ***
## Gestazione -78.8252 49.7474 -1.585 0.1132
## Lunghezza 10.3420 0.3040 34.024 < 2e-16 ***
## Cranio 10.7344 0.4260 25.195 < 2e-16 ***
## Tipo.partoNat 28.6370 12.1037 2.366 0.0181 *
## SessoM 76.9383 11.2333 6.849 9.32e-12 ***
## I(Gestazione^2) 1.4686 0.6622 2.218 0.0267 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 274.5 on 2493 degrees of freedom
## Multiple R-squared: 0.7273, Adjusted R-squared: 0.7266
## F-statistic: 1108 on 6 and 2493 DF, p-value: < 2.2e-16
Il modello 4 ha lo stesso R^2 del modello 3; sembra effettivamente esserci una non linearità (p_value = 0.0267), ma l’introduzione della nuova variabile ha aumentato il p_value di gestazione da 2.59e-16 a 0.1132; quindi il modello 3 è da preferire.
Per quanto riguarda le ipotesi di modello congiunto, possiamo provare a vedere le relazione congiunta tra Gestazione/Cranio e Gestazione/Lunghezza.
mod5 <- lm(Peso~Tipo.parto+Sesso+Gestazione*Lunghezza+Gestazione*Cranio)
summary(mod5)
##
## Call:
## lm(formula = Peso ~ Tipo.parto + Sesso + Gestazione * Lunghezza +
## Gestazione * Cranio)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1105.8 -183.6 -14.7 162.4 2677.3
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -328.28121 1108.04975 -0.296 0.7670
## Tipo.partoNat 27.80805 12.03760 2.310 0.0210 *
## SessoM 73.14955 11.18564 6.540 7.46e-11 ***
## Gestazione -138.20109 29.55732 -4.676 3.09e-06 ***
## Lunghezza 9.17478 3.76073 2.440 0.0148 *
## Cranio -7.45568 6.43949 -1.158 0.2471
## Gestazione:Lunghezza 0.03328 0.09749 0.341 0.7328
## Gestazione:Cranio 0.47458 0.16648 2.851 0.0044 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 273 on 2492 degrees of freedom
## Multiple R-squared: 0.7304, Adjusted R-squared: 0.7296
## F-statistic: 964.3 on 7 and 2492 DF, p-value: < 2.2e-16
Provando ad eliminare la relazione congiunta Gestazione/Lunghezza:
mod6 <- lm(Peso~Tipo.parto+Sesso+Lunghezza+Gestazione*Cranio)
summary(mod6)
##
## Call:
## lm(formula = Peso ~ Tipo.parto + Sesso + Lunghezza + Gestazione *
## Cranio)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1106.68 -183.65 -14.15 162.89 2680.73
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -319.73011 1107.57033 -0.289 0.77285
## Tipo.partoNat 27.81860 12.03542 2.311 0.02089 *
## SessoM 73.31415 11.17327 6.562 6.45e-11 ***
## Lunghezza 10.45458 0.30111 34.720 < 2e-16 ***
## Gestazione -138.28043 29.55117 -4.679 3.03e-06 ***
## Cranio -9.30632 3.47545 -2.678 0.00746 **
## Gestazione:Cranio 0.52232 0.09034 5.782 8.31e-09 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 273 on 2493 degrees of freedom
## Multiple R-squared: 0.7303, Adjusted R-squared: 0.7297
## F-statistic: 1125 on 6 and 2493 DF, p-value: < 2.2e-16
Il modello 6 ha un R^2 simile agli altri modelli, ma comunque più
alto, pertanto al momento da preferire.
Se proviamo a rimuovere
Tipo.parto:
mod7 <- lm(Peso~Sesso+Lunghezza+Gestazione*Cranio)
summary(mod7)
##
## Call:
## lm(formula = Peso ~ Sesso + Lunghezza + Gestazione * Cranio)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1125.48 -181.04 -13.99 163.92 2682.19
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -249.1238 1108.1125 -0.225 0.82214
## SessoM 73.3078 11.1830 6.555 6.72e-11 ***
## Lunghezza 10.4220 0.3010 34.620 < 2e-16 ***
## Gestazione -139.4557 29.5725 -4.716 2.54e-06 ***
## Cranio -9.4246 3.4781 -2.710 0.00678 **
## Gestazione:Cranio 0.5262 0.0904 5.821 6.62e-09 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 273.2 on 2494 degrees of freedom
## Multiple R-squared: 0.7298, Adjusted R-squared: 0.7292
## F-statistic: 1347 on 5 and 2494 DF, p-value: < 2.2e-16
Il modello 7 ha un R^2 adjusted di 0.7292, mentre il modello 6 di 0.7297, ma il modello 7 ha una variabile in meno, pertanto preferibile. Usiamo il criterio di valutazione AIC e BIC.
AIC(mod1,mod2,mod3,mod4,mod5,mod6,mod7)
## df AIC
## mod1 12 35172.09
## mod2 8 35175.16
## mod3 7 35181.82
## mod4 8 35178.89
## mod5 9 35152.40
## mod6 8 35150.52
## mod7 7 35153.87
BIC(mod1,mod2,mod3,mod4,mod5,mod6,mod7)
## df BIC
## mod1 12 35241.97
## mod2 8 35221.75
## mod3 7 35222.59
## mod4 8 35225.48
## mod5 9 35204.82
## mod6 8 35197.11
## mod7 7 35194.64
Il criterio AIC predilige il modello 6 più complesso, mentre il criterio BIC il modello 7 più semplice. Diamo priorità al criterio BIC e scegliamo il modello 7.
Possiamo provare anche ad utilizzare il metodo stepwise per vedere il modello migliore offerto dall’algoritmo:
stepwise.model <- step(mod1, direction="both",k=2)
## Start: AIC=28075.39
## Peso ~ Anni.madre + N.gravidanze + Fumatrici + Gestazione + Lunghezza +
## Cranio + Tipo.parto + Ospedale + Sesso
##
## Df Sum of Sq RSS AIC
## - Anni.madre 1 36392 186809099 28074
## - Fumatrici 1 89979 186862686 28075
## <none> 186772707 28075
## - Tipo.parto 1 447233 187219939 28079
## - N.gravidanze 1 448762 187221469 28079
## - Ospedale 2 686397 187459103 28081
## - Sesso 1 3611588 190384294 28121
## - Gestazione 1 5446558 192219264 28145
## - Cranio 1 45338051 232110758 28617
## - Lunghezza 1 87959790 274732497 29038
##
## Step: AIC=28073.88
## Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio +
## Tipo.parto + Ospedale + Sesso
##
## Df Sum of Sq RSS AIC
## - Fumatrici 1 90897 186899996 28073
## <none> 186809099 28074
## + Anni.madre 1 36392 186772707 28075
## - Tipo.parto 1 448222 187257321 28078
## - Ospedale 2 692738 187501837 28079
## - N.gravidanze 1 633756 187442855 28080
## - Sesso 1 3618736 190427835 28120
## - Gestazione 1 5412879 192221978 28143
## - Cranio 1 45588236 232397335 28618
## - Lunghezza 1 87950050 274759149 29036
##
## Step: AIC=28073.1
## Peso ~ N.gravidanze + Gestazione + Lunghezza + Cranio + Tipo.parto +
## Ospedale + Sesso
##
## Df Sum of Sq RSS AIC
## <none> 186899996 28073
## + Fumatrici 1 90897 186809099 28074
## + Anni.madre 1 37311 186862686 28075
## - Tipo.parto 1 440684 187340680 28077
## - Ospedale 2 701680 187601677 28078
## - N.gravidanze 1 610840 187510837 28079
## - Sesso 1 3602797 190502794 28119
## - Gestazione 1 5346781 192246777 28142
## - Cranio 1 45632149 232532146 28617
## - Lunghezza 1 88355030 275255027 29039
summary(stepwise.model)
##
## Call:
## lm(formula = Peso ~ N.gravidanze + Gestazione + Lunghezza + Cranio +
## Tipo.parto + Ospedale + Sesso)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1113.18 -181.16 -16.58 161.01 2620.19
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6707.4293 135.9438 -49.340 < 2e-16 ***
## N.gravidanze 12.3619 4.3325 2.853 0.00436 **
## Gestazione 31.9909 3.7896 8.442 < 2e-16 ***
## Lunghezza 10.3086 0.3004 34.316 < 2e-16 ***
## Cranio 10.4922 0.4254 24.661 < 2e-16 ***
## Tipo.partoNat 29.2803 12.0817 2.424 0.01544 *
## Ospedaleosp2 -11.0227 13.4363 -0.820 0.41209
## Ospedaleosp3 28.6408 13.4886 2.123 0.03382 *
## SessoM 77.4412 11.1756 6.930 5.36e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 273.9 on 2491 degrees of freedom
## Multiple R-squared: 0.7287, Adjusted R-squared: 0.7278
## F-statistic: 836.3 on 8 and 2491 DF, p-value: < 2.2e-16
AIC(stepwise.model, mod7)
## df AIC
## stepwise.model 10 35169.79
## mod7 7 35153.87
BIC(stepwise.model, mod7)
## df BIC
## stepwise.model 10 35228.03
## mod7 7 35194.64
Preferiamo il modello 7 rispetto al modello creato con il metodo
stepwise, confermato dai criteri AIC e BIC.
Vediamo se ci sono
problemi di multicollinearità:
car::vif(mod7, "predictor")
## GVIFs computed for predictors
## GVIF Df GVIF^(1/(2*Df)) Interacts With
## Sesso 1.047119 1 1.023288 --
## Lunghezza 2.101626 1 1.449698 --
## Gestazione 2.095429 3 1.131216 Cranio
## Cranio 2.095429 3 1.131216 Gestazione
## Other Predictors
## Sesso Lunghezza, Gestazione, Cranio
## Lunghezza Sesso, Gestazione, Cranio
## Gestazione Sesso, Lunghezza
## Cranio Sesso, Lunghezza
Tutti i VIF sono inferiori a 5 e pertanto possiamo escludere problemi di multicollinearità.
Una volta ottenuto il modello finale, valuteremo la sua capacità predittiva utilizzando metriche come R² e il Mean Squared Error (MSE). Un’attenzione particolare sarà rivolta all’analisi dei residui e alla presenza di valori influenti, che potrebbero distorcere le previsioni.
Procediamo facendo l’analisi dei residui del modello, che deve rispettare i criteri di normalità, omoschedasticità e indipendenza tra i residui.
par(mfrow = c (2,2))
plot(mod7, pch = 1, cex = 0.5, col = "orange")
Dal primo grafico si vede che i residui sono distribuiti attorno allo
zero, suggerendo che la maggior parte delle osservazioni è stata
“captata” dal modello.
Per quanto riguarda il secondo grafico,
idealmente i punti dovrebbero stare tutti sulla bisettrice; questo è
valido per tutti i valori centrali ma si vede una distorsione all’inizio
e alla fine della coda. Lo Shapiro test potrà confermare/smentire
l’ipotesi di normalità dei residui.
Nel terzo grafico i punti
sembrano assumere una forma che suggerisce omoschedasticità.
Il
quarto grafico mostra i valori di leva; l’osservazione 1551 supera il
valore di soglia 0.5 ma non il valore 1.
Procediamo con il test di normalità:
shapiro.test(residuals(mod7))
##
## Shapiro-Wilk normality test
##
## data: residuals(mod7)
## W = 0.97283, p-value < 2.2e-16
Il p_value è molto basso e pertando dobbiamo rifiutare l’ipotesi di normalità:
plot(density(residuals(mod7)))
Vediamo come vanno gli altri test:
lmtest::bptest(mod7)
##
## studentized Breusch-Pagan test
##
## data: mod7
## BP = 84.129, df = 5, p-value < 2.2e-16
Il test di Breusch-Pagan restituisce un valore molto basso e quindi dobbiamo rifiutare l’ipotesi di omoschedasticità.
lmtest::dwtest(mod7)
##
## Durbin-Watson test
##
## data: mod7
## DW = 1.9598, p-value = 0.1574
## alternative hypothesis: true autocorrelation is greater than 0
Il Durbin-Watson test resitutisce un p_value di 0.1574 e quindi non possiamo rifiutare H0, pertanto i residui tra loro risultano indipendenti.
Facciamo l’analisi dei valori di leva:
lev <- hatvalues(mod7)
plot(lev, pch = 1, cex = 0.5, col = "orange")
p = sum(lev)
n = length(lev)
soglia = 2*p/n
abline(h = soglia, col = 2)
Si mostrano molti valori di leva nello spazio di regressione.
lev[lev>soglia]
## 15 34 36 67 96 101
## 0.006662141 0.006279801 0.007212227 0.005426227 0.005630577 0.008131732
## 106 117 131 151 155 190
## 0.026268199 0.004869023 0.008412940 0.014212651 0.007352563 0.005411964
## 205 206 220 249 305 310
## 0.005463922 0.011641172 0.007464761 0.005754283 0.005582291 0.069150154
## 312 315 340 378 445 486
## 0.018074792 0.007390396 0.004924712 0.037966967 0.010029108 0.004864763
## 492 532 556 565 587 592
## 0.008962035 0.005163885 0.004906628 0.005749134 0.010296057 0.006400975
## 615 638 684 697 726 748
## 0.005875917 0.006669026 0.008813382 0.005940044 0.005207166 0.011875031
## 750 765 805 895 928 947
## 0.007484866 0.006658296 0.032331609 0.007245454 0.064330044 0.009033009
## 956 991 1014 1067 1091 1130
## 0.008522457 0.005361778 0.008313800 0.009558420 0.012876407 0.008435566
## 1134 1157 1181 1188 1200 1238
## 0.006131577 0.004849573 0.007613774 0.006437339 0.005577303 0.005377858
## 1248 1273 1283 1293 1294 1356
## 0.031703595 0.007523786 0.005045700 0.005792517 0.004828409 0.006613590
## 1357 1385 1395 1400 1420 1428
## 0.007322943 0.018458854 0.004860999 0.005565973 0.005162430 0.008194394
## 1429 1551 1553 1556 1593 1606
## 0.034041960 0.049713601 0.008491138 0.007022197 0.004856215 0.004941190
## 1610 1619 1634 1686 1693 1701
## 0.009675088 0.021318459 0.004912072 0.009107394 0.005632537 0.010675601
## 1712 1735 1780 1806 1809 1827
## 0.007046813 0.005052455 0.104978777 0.004875435 0.014807386 0.006025296
## 1858 1868 1959 1977 2016 2040
## 0.004976747 0.005821904 0.004853281 0.007349682 0.008643615 0.011855707
## 2062 2087 2089 2114 2115 2120
## 0.004993987 0.005004512 0.006437323 0.023588493 0.012412038 0.053672475
## 2140 2149 2175 2180 2200 2215
## 0.007748714 0.024089390 0.097179618 0.005077950 0.014684667 0.005553188
## 2216 2224 2225 2257 2307 2318
## 0.008016388 0.005781860 0.006053966 0.005966523 0.026422811 0.005451828
## 2337 2382 2391 2408 2433 2437
## 0.005605511 0.004882716 0.006088849 0.013137382 0.005000669 0.058284181
## 2452 2458 2478
## 0.109201379 0.009805826 0.005823114
Per quanto riguarda gli outliers:
plot(rstudent(mod7), pch = 1, cex = 0.5, col = "orange")
abline(h = c(-2,2), col = 2)
car::outlierTest(mod4)
## rstudent unadjusted p-value Bonferroni p
## 1551 10.094831 1.6380e-23 4.0949e-20
## 155 4.999623 6.1434e-07 1.5359e-03
## 1306 4.709843 2.6151e-06 6.5378e-03
Ci sono 3 osservazioni outliers (1551, 155 e 1306). Vediamo se superano la distanza di Cook:
cooks <- cooks.distance(mod7)
plot(cooks, pch = 1, cex = 0.75, col = "orange")
Come già visto precedentemente, l’osservazione 1551 supera il valore
di soglia 0.5, ma non quello di allarme 1, pertanto lo possiamo
mantenere nel modello.
Calcolo RMSE:
sqrt(sum(mean((Peso-predict(mod7))^2)))
## [1] 272.8809
Una volta validato il modello, lo useremo per fare previsioni pratiche. Ad esempio, potremo stimare il peso di una neonata considerando una madre alla terza gravidanza, non fumatrice, che partorirà alla 39esima settimana.
predict(mod7, newdata=data.frame(Sesso = 'F', Lunghezza = mean(Lunghezza), Gestazione = 39, Cranio = mean(Cranio)))
## 1
## 3240.937
mean(Peso)
## [1] 3284.081
La funzione predict restituisce il valore 3240.081 grammi per il peso della neonata.
Infine, utilizzeremo grafici e rappresentazioni visive per comunicare i risultati del modello.
Mostriamo l’impatto del numero di settimane di gestazione sul peso del neonato. Creiamo un grafico che mostra il peso del neonato in funzione del numero di settimane di gestazione a seconda che sia maschio o femmina.
library(ggplot2)
ggplot(data=dati)+
geom_point(aes(x=Gestazione, y=Peso, col=Sesso),position='jitter')+
geom_smooth(aes(x=Gestazione, y=Peso, col=Sesso), se=F, method = "lm")+
labs(title='Peso in funzione del numero di settimane di gestazione e del sesso')
## `geom_smooth()` using formula = 'y ~ x'
Allo stesso modo possiamo mostrare il peso per le variabili lunghezza e cranio dipendentemente dal sesso:
ggplot(data=dati)+
geom_point(aes(x=Lunghezza, y=Peso, col=Sesso),position='jitter')+
geom_smooth(aes(x=Lunghezza, y=Peso, col=Sesso), se=F, method = "lm")+
labs(title='Peso in funzione della lunghezza e del sesso')
## `geom_smooth()` using formula = 'y ~ x'
ggplot(data=dati)+
geom_point(aes(x=Cranio, y=Peso, col=Sesso),position='jitter')+
geom_smooth(aes(x=Cranio, y=Peso, col=Sesso), se=F, method = "lm")+
labs(title='Peso in funzione del diametro del cranio e del sesso')
## `geom_smooth()` using formula = 'y ~ x'
Il modello di regressione lineare multivariabile scelto utilizza le
variabili sesso, lunghezza, diametro del cranio e settimane di
gestazione con un valore R^2 adjuster pari a 0.7292.
Le variabili
età della madre e tabagismo non sono state incluse nel modello perchè
non apportavano un significativo cambiamento (seppure le informazioni
provenienti dalla letteratura sono differenti).