#import dei pacchetti
library(knitr)
library(moments)
library(kableExtra)
library(TeachingDemos)
library(dplyr)
library(Metrics)
library(car)
library(MASS)
library(ggplot2)
library(patchwork)
library(rgl)
df <- read.csv("neonati.csv")
df$Fumatrici <- factor(df$Fumatrici)
df$Tipo.parto <- factor(df$Tipo.parto)
df$Ospedale <- factor(df$Ospedale)
df$Sesso <- factor(df$Sesso)
attach(df)
n <- nrow(df)
print(paste("Il dataset ha",n, "righe"))
[1] "Il dataset ha 2500 righe"
Sono presenti 10 variabili.
Ci sono 4 variabili qualitative:
6 variabili quantitative:
selected_cols <- df[, c("Anni.madre","N.gravidanze","Gestazione", "Peso", "Lunghezza", "Cranio")]
stats <- data.frame(
Mean = apply(selected_cols, 2, mean),
Median = apply(selected_cols, 2, median),
Min = apply(selected_cols, 2, min),
Max = apply(selected_cols, 2, max),
IQR = apply(selected_cols, 2, IQR),
Variance = apply(selected_cols, 2, var),
Std_dev = apply(selected_cols, 2, sd),
Skewness = apply(selected_cols, 2, skewness),
Kurtosis = apply(selected_cols, 2, kurtosis)
)
stats$Kurtosis = stats$Kurtosis - 3
stats <- t(stats)
stats <- round(stats, 2)
colnames(stats) <- colnames(selected_cols)
kable(stats) %>%
kable_styling(full_width = FALSE, position = 'left')
| Anni.madre | N.gravidanze | Gestazione | Peso | Lunghezza | Cranio | |
|---|---|---|---|---|---|---|
| Mean | 28.16 | 0.98 | 38.98 | 3284.08 | 494.69 | 340.03 |
| Median | 28.00 | 1.00 | 39.00 | 3300.00 | 500.00 | 340.00 |
| Min | 0.00 | 0.00 | 25.00 | 830.00 | 310.00 | 235.00 |
| Max | 46.00 | 12.00 | 43.00 | 4930.00 | 565.00 | 390.00 |
| IQR | 7.00 | 1.00 | 2.00 | 630.00 | 30.00 | 20.00 |
| Variance | 27.81 | 1.64 | 3.49 | 275665.68 | 692.67 | 269.79 |
| Std_dev | 5.27 | 1.28 | 1.87 | 525.04 | 26.32 | 16.43 |
| Skewness | 0.04 | 2.51 | -2.07 | -0.65 | -1.51 | -0.79 |
| Kurtosis | 0.38 | 10.99 | 8.26 | 2.03 | 6.49 | 2.95 |
Dai parametri descrittivi delle variaibili quantitative si può osservare che per tutte le variabili i valori di media e mediana sono abbastanza vicini tra loro, indicando un’assenza di outlier significativi. Tuttavia, si osserva che la variabile Anni.madre ha un valore minimo di 0, il che porta a pensare che ci sia qualche errore di imputazione su alcuni dati. Un altro valore estremo sembra quello del massimo di Numero di gravidanze che risulta pari a 12. Per quanto riguarda la skewness, si osserva che la variabile degli anni è praticamente simmetrica, così come il peso; il numero di gravidanze ha un’asimmetria positiva mentre le restanti variabili hanno un’asimmetria negativa. Tutte le variabili risultano invece leptocurtiche ad eccezione della variabile anni.madre, che è praticamente mesocurtica.
par(mfrow = c(2, 2))
col_names = c("Anni.madre", "Peso", "Lunghezza", "Cranio")
for (col in col_names) {
plot(density(df[[col]]), main = paste("Density function of", col))
test_result <- shapiro.test(df[[col]])
p_value <- format(test_result$p.value, scientific = TRUE, digits = 3)
text(x = min(df[[col]], na.rm = TRUE),
y = max(density(df[[col]], na.rm = TRUE)$y)*0.9,
labels = paste("Shapiro test\np-value:", p_value),
pos = 4, col = "blue", cex = 0.8)
}
Osservando le distribuzioni delle densità di probabilità di queste
variabili si conferma quanto detto con la skewness e con la kurtosi,
infatti si osservano le code e la leptocurticità. Inoltre lo
Shapiro-test porta a rifiutare l’ipotesi che le distribuzioni siano
normali.
par(mfrow = c(1, 3))
discr_col = c("N.gravidanze", "Gestazione", "Anni.madre")
for (col in discr_col) {
x <- df[[col]]
h <- barplot(table(x), main = paste("Barplot of", col), col = "lightblue")
test_result <- shapiro.test(df[[col]])
p_value <- format(test_result$p.value, scientific = TRUE, digits = 3)
usr <- par("usr")
text(x = usr[2], y = usr[4] * 0.9,
labels = paste("Shapiro test\np-value:", p_value),
pos = 2, col = "blue", cex = 1)
}
Si può osservare la simmetria della variabile anni, e il fatto che sono
presenti dei dati corrispondenti ad anni inferiori a 13, ma sono in
numero esiguo e non sembrano influenzare la forma della
distribuzione.
Si osserva inoltre come il numero di gravidanze abbia un conteggio decrescente, ovvero la maggior parte delle donne ereno alla prima o seconda gravidanza alla nascita del bambino.
Per quanto riguarda la variabile gestazione, si osserva che la distribuzione è centrata sulle 40 settimane e ha una coda negativa ad indicare che come outlier le nascite premature avvengono maggiormente rispetto a nascite tardive.
Con i seguenti grafici si mostrano i boxplot delle variabili quantitative:
par(mfrow = c(2, 3))
num_cols <- c("Anni.madre", "N.gravidanze", "Gestazione", "Peso", "Lunghezza", "Cranio" )
for (col in num_cols) {
x <- na.omit(df[[col]])
boxplot(x, main = paste("Boxplot of", col), col = "lightblue")
}
Si analizzano gli outlier della variabile anni.madre
kable(df[df$Anni.madre <= "14", ])%>%
kable_styling(full_width = FALSE, position = 'left')
| Anni.madre | N.gravidanze | Fumatrici | Gestazione | Peso | Lunghezza | Cranio | Tipo.parto | Ospedale | Sesso | |
|---|---|---|---|---|---|---|---|---|---|---|
| 138 | 13 | 0 | 0 | 38 | 2760 | 470 | 325 | Nat | osp2 | F |
| 1075 | 14 | 1 | 0 | 39 | 3510 | 490 | 365 | Nat | osp2 | M |
| 1152 | 1 | 1 | 0 | 41 | 3250 | 490 | 350 | Nat | osp2 | F |
| 1380 | 0 | 0 | 0 | 39 | 3060 | 490 | 330 | Nat | osp3 | M |
| 1532 | 14 | 0 | 0 | 39 | 3550 | 500 | 355 | Ces | osp1 | M |
Per quanto poco probabili gli anni 13 e 14 potrebbero essere corretti, mentre gli anni 1 e 0 sono sicuramente errori di imputazione. Si decide di sostituire questi valori con la media degli anni delle madri presenti nel dataset.
excluded_val <- c(1152,1380)
mean_age <- mean(df$Anni.madre[-excluded_val])
Anni.madre[excluded_val] <- mean_age
Si riosserva il boxplot Anni.madre:
boxplot(Anni.madre, main = paste("Boxplot of Anni.madre"), col="lightblue")
#function for tables creation
table_freq <- function(variable, n){
frq_ass <- table(variable)
frq_rel <- frq_ass/n
distr_freq <- cbind(frq_ass, frq_rel)
return(distr_freq)
}
qual_cols <- c("Fumatrici", "Tipo.parto", "Ospedale", "Sesso")
tables <- list()
for (col in qual_cols) {
tables[[col]] = table_freq(df[[col]], n)
}
kable(tables$Fumatrici, caption = "Fumatrici")%>%
kable_styling(full_width = FALSE, position = 'left')
| frq_ass | frq_rel | |
|---|---|---|
| 0 | 2396 | 0.9584 |
| 1 | 104 | 0.0416 |
kable(tables$Tipo.parto, caption = "Tipo parto")%>%
kable_styling(full_width = FALSE, position = 'left')
| frq_ass | frq_rel | |
|---|---|---|
| Ces | 728 | 0.2912 |
| Nat | 1772 | 0.7088 |
kable(tables$Ospedale, caption = "Ospedale")%>%
kable_styling(full_width = FALSE, position = 'left')
| frq_ass | frq_rel | |
|---|---|---|
| osp1 | 816 | 0.3264 |
| osp2 | 849 | 0.3396 |
| osp3 | 835 | 0.3340 |
kable(tables$Sesso, caption="Sesso")%>%
kable_styling(full_width = FALSE, position = 'left')
| frq_ass | frq_rel | |
|---|---|---|
| F | 1256 | 0.5024 |
| M | 1244 | 0.4976 |
Dalle tabelle di frequenza si può osservare che i dati sono ben distribuiti nei tre ospedali e anche tra i due sessi. Si osserva invece una preponderanza di parti naturali rispetto ai cesarei (circa il 70% contro il 30%) e una forte maggioranza (96%) di donne non fumatrici rispetto alle fumatrici.
H0: Non c’è differenza nel numero di cesarei effettuati nei tre ospedali
H1: C’è differenza significativa nel numero di cesarei effettuati nei tre ospedali
# Tabella di contingenza
freq_parti <- table(Ospedale, Tipo.parto)
kable(freq_parti) %>%
kable_styling(full_width = FALSE, position = 'left')
| Ces | Nat | |
|---|---|---|
| osp1 | 242 | 574 |
| osp2 | 254 | 595 |
| osp3 | 232 | 603 |
# Test del Chi-quadro
chi <- chisq.test(freq_parti)
print(chi)
Pearson's Chi-squared test
data: freq_parti
X-squared = 1.0972, df = 2, p-value = 0.5778
Il test del chi quadro mostra se la proporzione di cesarei rispetto ai naturali varia da un ospedale all’altro. Il p-value superiore a 0.05 indica l’accettazione dell’ipotesi nulla, per cui non c’è differenza significativa tra le proporzioni dei cesarei nei vari ospedali.
H0: Non c’è differenza tra la media della variabile considerata del campione in analisi e quella della popolazione
H1: C’è una differenza significativa tra la media della variabile considerata del campione in analisi e quella della popolazione
#population values
pop_weight = 3300
pop_lungh = 500
#t-tests
t_peso <- t.test(Peso, mu = pop_weight, conf.level = 0.95)
t_lungh <- t.test(Lunghezza, mu = pop_lungh, conf.level = 0.95)
t_test_results <-
data.frame(
Variabile = c("Peso", "Lunghezza"),
media_pop = round(c(pop_weight, pop_lungh), 2),
media_obs = round(c(t_peso$estimate,t_lungh$estimate), 2),
t_obs = round(c(t_peso$statistic, t_lungh$statistic),2),
p_value = c(round(t_peso$p.value, 3), format(t_lungh$p.value, scientific = T, digits = 3))
)
kable(t_test_results)%>%
kable_styling(full_width = FALSE, position = 'left')
| Variabile | media_pop | media_obs | t_obs | p_value |
|---|---|---|---|---|
| Peso | 3300 | 3284.08 | -1.52 | 0.13 |
| Lunghezza | 500 | 494.69 | -10.08 | 1.81e-23 |
Il t-test sul peso neonatale mostra un p-value maggiore di 0.05, inoltre l’intervallo di confidenza al 95% comprende la media della popolazione. Pertanto, si ritiene accettata l’ipotesi nulla e quindi non significativa la differenza della media del campione con quella della popolazione.
Nel caso della lunghezza, invece, il t-test ha dato un valore molto prossimo a 0 e comunque <<0.05, inoltre l’intervallo di confidenza non contiene la media della popolazione. Pertanto, si rifiuta l’ipotesi nulla e risulta esserci una differenza statisticamente significativa tra la media della lunghezza neonatale del campione e quella della popolazione. In particolare, in media i valori di lunghezza neonatale sono inferiori alla media della popolazione. Infatti, osservando sia il boxplot sia la distribuzione della variabile, si può osservare che presenta molti outlier nei valori inferiori alla media ed ha un’asimmetria negativa.
Nei grafici sottostanti si mostrano le distribuzioni t di student con i limiti al 95% di confidenza e il punto in cui ricade la statistica di test.
par(mfrow = c(1, 2))
dof <- 2499
t_obs <- -1.516
alpha <- 0.05
t_val <- seq(-4, +4, length = 1000)
t_critico_dx <- qt(1 - alpha/2, dof)
t_critico_sx <- qt(alpha/2, dof)
plot(t_val, dt(t_val, dof), type = "l", lwd = 2,
ylab = "Densità", xlab = "t",
main = "Distribuzione t-student peso neonatale")
abline(v = t_critico_dx, col = "red", lwd = 2, lty = 2)
abline(v = t_critico_sx, col = "red", lwd = 2, lty = 2)
points(t_obs, dt(t_obs, dof), col = "blue", pch = 16, cex = 2)
legend("topright", legend = c("alpha = 0.05", "t osservato"),
col = c("red", "blue"), lty = c(2,NA),lwd = c(2, NA), pch = c(NA, 16), pt.cex = c(NA,2))
dof <- 2499
t_obs <- -10.84
alpha <- 0.05
t_val <- seq(-15, +15, length = 1000)
t_critico_dx <- qt(1 - alpha/2, dof)
t_critico_sx <- qt(alpha/2, dof)
plot(t_val, dt(t_val, dof), type = "l", lwd = 2,
ylab = "Densità", xlab = "t",
main = "Distribuzione t-student lunghezza neonatale")
abline(v = t_critico_dx, col = "red", lwd = 2, lty = 2)
abline(v = t_critico_sx, col = "red", lwd = 2, lty = 2)
points(t_obs, dt(t_obs, dof), col = "blue", pch = 16, cex = 2)
legend("topright", legend = c("alpha = 0.05", "t osservato"),
col = c("red", "blue"), lty = c(2,NA),lwd = c(2, NA), pch = c(NA, 16), pt.cex = c(NA,2))
H0: Non c’è differenza tra le misure antropometriche delle femmine rispetto ai maschi
H1: c’è una differenza significativa tra le misure antropometriche delle femmine rispetto ai maschi
Si visualizzano i boxplot delle variabili
par(mfrow = c(1, 3))
boxplot(Peso~Sesso,main = "Peso vs Sesso", col=c("lightblue", "lightgreen"))
boxplot(Lunghezza~Sesso, main = "Lunghezza vs Sesso", col=c("lightblue", "lightgreen"))
boxplot(Cranio~Sesso, main = "Cranio vs Sesso", col=c("lightblue", "lightgreen"))
Si effettuano i test e si riportano in tabella
t_peso <- t.test(Peso ~ Sesso, data = df)
t_lungh <- t.test(Lunghezza ~ Sesso, data = df)
t_cranio <- t.test(Cranio ~ Sesso, data = df)
t_test_results <-
data.frame(
Variabile = c("Peso", "Lunghezza", "Cranio"),
media_M = round(c(mean(Peso[Sesso == "M"]), mean(Lunghezza[Sesso == "M"]), mean(Cranio[Sesso == "M"])), 2),
media_F = round(c(mean(Peso[Sesso == "F"]), mean(Lunghezza[Sesso == "F"]), mean(Cranio[Sesso == "F"])), 2),
t_obs = round(c(t_peso$statistic, t_lungh$statistic, t_cranio$statistic),2),
p_value = c(format(t_peso$p.value, scientific = T, digits = 3), format(t_lungh$p.value, scientific = T, digits = 3),format(t_cranio$p.value, scientific = T, digits = 3))
)
kable(t_test_results)%>%
kable_styling(full_width = FALSE, position = 'left')
| Variabile | media_M | media_F | t_obs | p_value |
|---|---|---|---|---|
| Peso | 3408.22 | 3161.13 | -12.11 | 8.03e-33 |
| Lunghezza | 499.67 | 489.76 | -9.58 | 2.24e-21 |
| Cranio | 342.45 | 337.63 | -7.41 | 1.72e-13 |
Per tutte le caratteristiche antropometriche il t-test ha mostrato un p-value inferiore a 0.05, tale per cui si rifiutano le ipotesi nulle ed emerge una differenza statisticamente significativa tra la categoria dei neonati maschi e dei neonati femmine. I neonati maschi risultano avere in media un peso, una lunghezza e le dimensioni del cranio maggiori rispetto a quelle delle neonate femmine.
Si osservano le correlazioni tra le variabili del dataset, escludendo quelle qualitative
panel.cor <- function(x, y, digits = 2, prefix = "", cex.cor, ...)
{
usr <- par("usr"); on.exit(par(usr=usr))
par(usr = c(0, 1, 0, 1))
r <- (cor(x, y))
txt <- format(c(r, 1), 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)
}
df_num <- dplyr::select(df, where(is.numeric))
pairs(df_num, lower.panel = panel.cor, upper.panel = panel.smooth)
Dalla matrice di correlazione si può osservare una forte correlazione
positiva tra peso, lunghezza, cranio e periodo di gestazione. Tra
gestazione e peso si osserva una leggera tendenza ad una relazione
quadratica, così come tra peso e lunghezza.
Per le variabili qualitative si osservano i boxplot.
par(mfrow=c(2,2))
boxplot(Peso~Sesso, col=c("lightblue", "lightgreen"))
boxplot(Peso~Fumatrici, col=c("lightblue", "lightgreen"))
boxplot(Peso~Tipo.parto, col=c("lightblue", "lightgreen"))
boxplot(Peso~Ospedale, col=c("lightblue", "lightgreen", "orange"))
Per il sesso è stato già osservato precedentemente che la differenza tra le medie è signficiativa. Si effettua un t-test allo stesso modo relativamente alle altre variabili.
H0: Non c’è differenza nel peso medio del neonato in base alla categoria della variabile (fumatrice o non, oppure parto naturale o cesareo)
H1: C’è una differenza significativa tra il peso di un neonato relativamente alla categoria della variabile
t_fum <- t.test(Peso ~ Fumatrici, data = df)
t_parto <- t.test(Peso ~ Tipo.parto, data = df)
fum_parto_res <-
data.frame(
Variabile = c("Fumatrici", "Tipo.parto"),
t_obs = round(c(t_fum$statistic, t_parto$statistic),2),
p_value = round(c(t_fum$p.value, t_parto$p.value), 3)
)
kable(fum_parto_res)%>%
kable_styling(full_width = FALSE, position = 'left')
| Variabile | t_obs | p_value |
|---|---|---|
| Fumatrici | 1.03 | 0.303 |
| Tipo.parto | -0.13 | 0.897 |
Il test mostra un p-value superiore a 0.05 per entrambe le variabili, pertanto si accettano le ipotesi nulle e non c’è differenza significativa tra il peso di un neonato figlio di una fumatrice e quello di una non fumatrice, così come tra quello di un neonato nato da un cesareo o da un parto naturale. Pertanto queste due variabili potrebbero non essere rilevanti per il modello di regressione.
pairwise.t.test(Peso, Ospedale, paired = F, pool.sd = T, p.adjust.method = "bonferroni")
Pairwise comparisons using t tests with pooled SD
data: Peso and Ospedale
osp1 osp2
osp2 1.00 -
osp3 0.33 0.33
P value adjustment method: bonferroni
I p-value sono tutti superiori a 0.05 quindi non c’è differenza significativa tra il peso dei neonati nei tre ospedali. Pertanto anche in questo caso non ci si aspetta che la variabile abbia un peso rilevante nel modello di regressione.
Modello di regressione con tutte le variabili:
mod1<-lm(df$Peso~ . , data = df)
summary(mod1)
Call:
lm(formula = df$Peso ~ ., data = df)
Residuals:
Min 1Q Median 3Q Max
-1124.40 -181.66 -14.42 160.91 2611.89
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -6738.4762 141.3087 -47.686 < 2e-16 ***
Anni.madre 0.8921 1.1323 0.788 0.4308
N.gravidanze 11.2665 4.6608 2.417 0.0157 *
Fumatrici1 -30.1631 27.5386 -1.095 0.2735
Gestazione 32.5696 3.8187 8.529 < 2e-16 ***
Lunghezza 10.2945 0.3007 34.236 < 2e-16 ***
Cranio 10.4707 0.4260 24.578 < 2e-16 ***
Tipo.partoNat 29.5254 12.0844 2.443 0.0146 *
Ospedaleosp2 -11.2095 13.4379 -0.834 0.4043
Ospedaleosp3 28.0958 13.4957 2.082 0.0375 *
SessoM 77.5409 11.1776 6.937 5.08e-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.2 on 10 and 2489 DF, p-value: < 2.2e-16
Descrizione del peso delle variabili in questo modello:
Le variabili più significative sono dunque: Gestazione, Lunghezza e Cranio. Inoltre è significativa la differenza tra maschi e femmine. L’R2 aggiustato di questo modello è circa 0.73, ad indicare che è in grado di spiegare il 73% della variabilità del peso neonatale.
Si provano ad aggiungere gli effetti quadratici di gestazione, lunghezza e cranio
mod2 <- update(mod1,~.+I(Gestazione^2)+I(Lunghezza^2)+I(Cranio^2))
summary(mod2)
Call:
lm(formula = df$Peso ~ Anni.madre + N.gravidanze + Fumatrici +
Gestazione + Lunghezza + Cranio + Tipo.parto + Ospedale +
Sesso + I(Gestazione^2) + I(Lunghezza^2) + I(Cranio^2), data = df)
Residuals:
Min 1Q Median 3Q Max
-1157.69 -180.60 -8.68 156.80 1441.87
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.360e+03 1.159e+03 -1.173 0.24085
Anni.madre 4.493e-01 1.108e+00 0.405 0.68529
N.gravidanze 1.377e+01 4.562e+00 3.017 0.00257 **
Fumatrici1 -2.377e+01 2.693e+01 -0.883 0.37752
Gestazione 3.848e+02 6.737e+01 5.712 1.25e-08 ***
Lunghezza -2.919e+01 4.428e+00 -6.593 5.24e-11 ***
Cranio -5.465e+00 9.787e+00 -0.558 0.57667
Tipo.partoNat 2.712e+01 1.182e+01 2.295 0.02180 *
Ospedaleosp2 -1.114e+01 1.314e+01 -0.848 0.39670
Ospedaleosp3 3.085e+01 1.320e+01 2.338 0.01949 *
SessoM 7.198e+01 1.097e+01 6.561 6.49e-11 ***
I(Gestazione^2) -4.498e+00 8.836e-01 -5.091 3.82e-07 ***
I(Lunghezza^2) 4.074e-02 4.536e-03 8.982 < 2e-16 ***
I(Cranio^2) 2.338e-02 1.443e-02 1.620 0.10527
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 267.7 on 2486 degrees of freedom
Multiple R-squared: 0.7413, Adjusted R-squared: 0.74
F-statistic: 548.1 on 13 and 2486 DF, p-value: < 2.2e-16
Lunghezza e gestazione al quadrato risultano molto significative, mentre cranio no. Inoltre perde significatività anche la forma lineare della variabile cranio. R2 aumenta da 0.72 a 0.74
Si decide di rimuovere la variabile cranio al quadrato
mod3 <- update(mod2,~.-I(Cranio^2))
summary(mod3)
Call:
lm(formula = df$Peso ~ Anni.madre + N.gravidanze + Fumatrici +
Gestazione + Lunghezza + Cranio + Tipo.parto + Ospedale +
Sesso + I(Gestazione^2) + I(Lunghezza^2), data = df)
Residuals:
Min 1Q Median 3Q Max
-1162.18 -178.48 -8.91 156.48 1374.43
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -2.535e+03 9.043e+02 -2.803 0.00510 **
Anni.madre 4.853e-01 1.109e+00 0.438 0.66160
N.gravidanze 1.379e+01 4.563e+00 3.023 0.00253 **
Fumatrici1 -2.420e+01 2.693e+01 -0.899 0.36892
Gestazione 3.447e+02 6.267e+01 5.500 4.18e-08 ***
Lunghezza -3.216e+01 4.032e+00 -7.976 2.29e-15 ***
Cranio 1.038e+01 4.189e-01 24.782 < 2e-16 ***
Tipo.partoNat 2.740e+01 1.182e+01 2.319 0.02048 *
Ospedaleosp2 -1.129e+01 1.314e+01 -0.859 0.39047
Ospedaleosp3 3.020e+01 1.320e+01 2.288 0.02220 *
SessoM 7.228e+01 1.097e+01 6.587 5.45e-11 ***
I(Gestazione^2) -3.982e+00 8.243e-01 -4.831 1.44e-06 ***
I(Lunghezza^2) 4.376e-02 4.135e-03 10.582 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 267.8 on 2487 degrees of freedom
Multiple R-squared: 0.7411, Adjusted R-squared: 0.7398
F-statistic: 593.1 on 12 and 2487 DF, p-value: < 2.2e-16
In questo modo si perde leggermente in R2, che però rimane circa 0.74, ma torna la significatività della variabile cranio al primo grado.
Si rimuovono le variabili non significative
mod4 <- update(mod3,~.-Anni.madre-Ospedale-Fumatrici)
summary(mod4)
Call:
lm(formula = df$Peso ~ N.gravidanze + Gestazione + Lunghezza +
Cranio + Tipo.parto + Sesso + I(Gestazione^2) + I(Lunghezza^2),
data = df)
Residuals:
Min 1Q Median 3Q Max
-1172.27 -178.53 -11.31 163.11 1405.90
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -2.426e+03 9.049e+02 -2.681 0.007384 **
N.gravidanze 1.474e+01 4.245e+00 3.472 0.000525 ***
Gestazione 3.373e+02 6.264e+01 5.384 7.98e-08 ***
Lunghezza -3.199e+01 4.034e+00 -7.931 3.25e-15 ***
Cranio 1.041e+01 4.190e-01 24.851 < 2e-16 ***
Tipo.partoNat 2.799e+01 1.183e+01 2.365 0.018088 *
SessoM 7.260e+01 1.099e+01 6.607 4.77e-11 ***
I(Gestazione^2) -3.885e+00 8.237e-01 -4.716 2.54e-06 ***
I(Lunghezza^2) 4.358e-02 4.137e-03 10.535 < 2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 268.2 on 2491 degrees of freedom
Multiple R-squared: 0.7398, Adjusted R-squared: 0.739
F-statistic: 885.4 on 8 and 2491 DF, p-value: < 2.2e-16
Ora nel modello vi sono tutte variabili significative ed è in grado di spiegare il 74% della variabilità del peso neonatale (R2 aggiustato).
Si analizzano le interazioni tra diverse variabili nel modello:
mod5 <- update(mod4,~.+Lunghezza*Cranio+Anni.madre*Gestazione)
summary(mod5)
Call:
lm(formula = df$Peso ~ N.gravidanze + Gestazione + Lunghezza +
Cranio + Tipo.parto + Sesso + I(Gestazione^2) + I(Lunghezza^2) +
Anni.madre + Lunghezza:Cranio + Gestazione:Anni.madre, data = df)
Residuals:
Min 1Q Median 3Q Max
-1165.36 -181.67 -12.13 162.44 1333.87
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.777e+03 1.239e+03 -1.434 0.151819
N.gravidanze 1.390e+01 4.556e+00 3.051 0.002304 **
Gestazione 2.271e+02 7.115e+01 3.193 0.001428 **
Lunghezza -3.011e+01 4.091e+00 -7.360 2.48e-13 ***
Cranio 2.085e+01 5.081e+00 4.102 4.22e-05 ***
Tipo.partoNat 2.724e+01 1.182e+01 2.304 0.021309 *
SessoM 7.325e+01 1.098e+01 6.674 3.06e-11 ***
I(Gestazione^2) -2.965e+00 8.913e-01 -3.327 0.000891 ***
I(Lunghezza^2) 4.907e-02 5.063e-03 9.692 < 2e-16 ***
Anni.madre -5.240e+01 2.046e+01 -2.561 0.010507 *
Lunghezza:Cranio -2.139e-02 1.039e-02 -2.059 0.039597 *
Gestazione:Anni.madre 1.365e+00 5.264e-01 2.593 0.009578 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 267.8 on 2488 degrees of freedom
Multiple R-squared: 0.741, Adjusted R-squared: 0.7398
F-statistic: 647 on 11 and 2488 DF, p-value: < 2.2e-16
L’interazione tra cranio e lunghezza e quella tra gestazione e anni.madre risultano significative, tuttavia l’R2 rimane praticamente invariato, pertanto si sceglie di non includere queste variabili che aumenterebbero la complessità del modello e di scegliere il mod4.
Per completezza, si considera anche il modello con solo le variabili lineari e senza quelle non significative:
mod6 <- update(mod1,~.-Anni.madre-Ospedale-Fumatrici)
summary(mod6)
Call:
lm(formula = df$Peso ~ N.gravidanze + Gestazione + Lunghezza +
Cranio + Tipo.parto + Sesso, data = df)
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
Si verifica la scelta del modello con il criterio BIC:
bic <- BIC(mod1, mod2, mod3, mod4, mod5, mod6)
kable(bic)%>%
kable_styling(full_width = FALSE, position = 'left')
| df | BIC | |
|---|---|---|
| mod1 | 12 | 35241.84 |
| mod2 | 15 | 35147.92 |
| mod3 | 14 | 35142.74 |
| mod4 | 10 | 35123.36 |
| mod5 | 13 | 35135.79 |
| mod6 | 8 | 35221.75 |
Il modello con i BIC più basso è quello selezionato precedentemente ovvero il modello 4.
Si effettua un test dell’ANOVA tra il modello completamente lineare (mod6) e quello con i termini quadratici scelto (mod4)
anova(mod4, mod6)
Analysis of Variance Table
Model 1: df$Peso ~ N.gravidanze + Gestazione + Lunghezza + Cranio + Tipo.parto +
Sesso + I(Gestazione^2) + I(Lunghezza^2)
Model 2: df$Peso ~ N.gravidanze + Gestazione + Lunghezza + Cranio + Tipo.parto +
Sesso
Res.Df RSS Df Sum of Sq F Pr(>F)
1 2491 179236346
2 2493 187601677 -2 -8365330 58.13 < 2.2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Il p-value risulta molto prossimo a 0, ad indicare che l’aggiunta dei termini quadratici è molto significativa per la varianza spiegata dal modello.
Si calcolano anche gli rmse dei modelli e si riportano le informazioni nella seguente tabella
y_oss <- df$Peso
rmse <- c()
r2_adj <- c()
for (el in list(mod1, mod2, mod3, mod4, mod5, mod6)){
rmse <- c(rmse, rmse(y_oss, fitted(el)))
r2_adj <- c(r2_adj, summary(el)$adj.r.squared)
}
tabella <-
data.frame(
"Modello" = c("mod1", "mod2", "mod3", "mod4", "mod5", "mod6"),
"R2_adj" = r2_adj,
"RMSE" = rmse,
"BIC" = bic$BIC
)
kable(tabella) %>%
kable_styling(full_width = FALSE, position = 'left')
| Modello | R2_adj | RMSE | BIC |
|---|---|---|---|
| mod1 | 0.7278038 | 273.3222 | 35241.84 |
| mod2 | 0.7399761 | 266.9799 | 35147.92 |
| mod3 | 0.7398061 | 267.1208 | 35142.74 |
| mod4 | 0.7389825 | 267.7584 | 35123.36 |
| mod5 | 0.7398197 | 267.1676 | 35135.79 |
| mod6 | 0.7270194 | 273.9355 | 35221.75 |
Il modello con RMSE più basso sarebbe il 2, tuttavia esso considera anche variabili non significative che ne aumentano la complessità. Inoltre, come nel caso dell’R2, l’aumento del valore di RMSE, in particolare nel modello 4, è di piccola entità. Si sceglie dunque il modello 4 che è anche quello con BIC minore.
Si verifica la presenza di multicollinearità nel modello:
vif_4 <- vif(mod4)
vif_df <- data.frame(VIF = vif_4)
kable(vif_df) %>%
kable_styling(full_width = FALSE, position = 'left')
| VIF | |
|---|---|
| N.gravidanze | 1.026094 |
| Gestazione | 475.891404 |
| Lunghezza | 391.454121 |
| Cranio | 1.645147 |
| Tipo.parto | 1.003897 |
| Sesso | 1.048541 |
| I(Gestazione^2) | 453.552580 |
| I(Lunghezza^2) | 372.926478 |
I VIF mostrano multicollinearità tra le variabili e i loro quadrati, come è normale che avvenga. Non c’è però multicollinearità tra le variabili di primo grado, infatti, se si calcolano i VIF per il primo modello, ovvero quello che non contiene i termini quadratici, si può osservare come tutte le variabili abbiano valori inferiori a 5.
vif_1 <- round(vif(mod1), 3)
kable(vif_1)%>%
kable_styling(full_width = FALSE, position = 'left')
| GVIF | Df | GVIF^(1/(2*Df)) | |
|---|---|---|---|
| Anni.madre | 1.187 | 1 | 1.090 |
| N.gravidanze | 1.186 | 1 | 1.089 |
| Fumatrici | 1.007 | 1 | 1.004 |
| Gestazione | 1.696 | 1 | 1.302 |
| Lunghezza | 2.086 | 1 | 1.444 |
| Cranio | 1.631 | 1 | 1.277 |
| Tipo.parto | 1.004 | 1 | 1.002 |
| Ospedale | 1.004 | 2 | 1.001 |
| Sesso | 1.041 | 1 | 1.020 |
par(mfrow=c(2,2))
plot(mod4)
I residui sono distribuiti in modo abbastanza randomico attorno alla media.
Il Q-Q plot invece mostra una deviazione dalla normalità a valori alti e a valori bassi
La varianza sembra rimanere costante
Dal grafico dei residui il valore 1551 sembra essere particolarmente influente e superare la distanza di cook.
Si effettuano i test statistici
#shapiro-wilk per la normalità
res_sh <- shapiro.test(residuals(mod4))
#breusch-pagan per l'omoschedasticità
res_bp <- lmtest::bptest(mod4)
#darwin-watson èer la non correlazione
res_dw <- lmtest::dwtest(mod4)
res_test_results <-
data.frame(
Test = c("Shapiro-Wilk", "Breusch-Pagan", "Durbin-Watson"),
Caratteristica_testata = c("Normalità", "Omoschedasticità", "Autocorrelazione"),
p_value = c(format(res_sh$p.value, scientific = T, digits = 3), format(res_bp$p.value, scientific = T, digits = 3), round(res_dw$p.value, 3))
)
kable(res_test_results)%>%
kable_styling(full_width = FALSE, position = 'left')
| Test | Caratteristica_testata | p_value |
|---|---|---|
| Shapiro-Wilk | Normalità | 8.11e-13 |
| Breusch-Pagan | Omoschedasticità | 5.79e-18 |
| Durbin-Watson | Autocorrelazione | 0.098 |
Shapiro-wilk p-value molto basso: si rifiuta l’ipotesi di normalità
Breusch-Pagan p-value molto basso: si rifiuta l’ipotesi di omoschedasticità
Darwin-Watson p-value leggermente sopra a 0.05: si accetta l’ipotesi di autocorrelazione dei residui.
Tutti e tre i test dei residui non risultano passati.
Si indagano i valori di leverage
lev<-hatvalues(mod4)
plot(lev)
p<-sum(lev)
n<-length(lev)
soglia=2*p/n
abline(h=soglia,col=2)
Si evidenziano diversi valori leverage al di sopra della soglia.
Si indagano gli outliers
plot(rstudent(mod4))
abline(h=c(-2,2))
a <- outlierTest(mod4)
kable(data.frame("Bonf p-val" = format(a$bonf.p, scientific=T, digits = 3))) %>%
kable_styling(full_width = FALSE, position = 'left')
| Bonf.p.val | |
|---|---|
| 1551 | 3.36e-06 |
| 1306 | 2.13e-03 |
| 155 | 2.17e-02 |
| 1399 | 2.90e-02 |
| 1694 | 2.94e-02 |
Ci sono diversi outliers, in particolare 5 hanno un p-value significativo.
Si indaga quali valori, tra leverage e outliers, superano la distanza di cook
cook<-cooks.distance(mod4)
plot(cook,ylim = c(0,2))
text(x = 500, y = 1.8,
labels = paste("Max cook distance:", round(max(cook), 2)),
, col = "blue", cex = 0.8)
Un valore risulta avere una distanza di cook molto alta, superiore a 1. Si identifica nel dataset la riga corrispondente.
kable(df[which.max(cook), ]) %>%
kable_styling(full_width = FALSE, position = 'left')
| Anni.madre | N.gravidanze | Fumatrici | Gestazione | Peso | Lunghezza | Cranio | Tipo.parto | Ospedale | Sesso | |
|---|---|---|---|---|---|---|---|---|---|---|
| 1551 | 35 | 1 | 0 | 38 | 4370 | 315 | 374 | Nat | osp3 | F |
Si rimuove la riga identificata che ha la distanza di cook superiore a 1 e si prova a rifare il modello di regressione
df_2 <- df[-1551, ]
mod1_n<-lm(df_2$Peso~ . , data = df_2)
mod2_n <- update(mod1_n,~.+I(Gestazione^2)+I(Lunghezza^2)+I(Cranio^2))
mod3_n <- update(mod2_n,~.-I(Cranio^2))
mod4_n <- update(mod3_n,~.-Anni.madre-Ospedale-Fumatrici)
mod5_n <- update(mod4_n,~.+Lunghezza*Cranio+Anni.madre*Gestazione)
mod6_n <- update(mod1_n,~.-Anni.madre-Ospedale-Fumatrici)
y_oss <- df_2$Peso
rmse_n <- c()
r2_adj_n <- c()
for (el in list(mod1_n, mod2_n, mod3_n, mod4_n, mod5_n, mod6_n)){
rmse_n <- c(rmse_n, rmse(y_oss, fitted(el)))
r2_adj_n <- c(r2_adj_n, summary(el)$adj.r.squared)
}
mod_no_outlier <-
data.frame(
"Modello" = c("mod1_n", "mod2_n","mod3_n","mod4_n","mod5_n","mod6_n"),
"R2_adj" = r2_adj_n,
"RMSE" = rmse_n,
"BIC" = BIC(mod1_n, mod2_n, mod3_n, mod4_n, mod5_n, mod6_n)$BIC
)
kable(mod_no_outlier) %>%
kable_styling(full_width = FALSE, position = 'left')
| Modello | R2_adj | RMSE | BIC |
|---|---|---|---|
| mod1_n | 0.7378210 | 268.0693 | 35130.78 |
| mod2_n | 0.7437090 | 264.8823 | 35094.48 |
| mod3_n | 0.7430333 | 265.2845 | 35094.24 |
| mod4_n | 0.7423658 | 265.8425 | 35073.45 |
| mod5_n | 0.7434381 | 265.1288 | 35083.48 |
| mod6_n | 0.7372214 | 268.5913 | 35109.21 |
In questi modelli, in cui è stato rimosso l’outlier, valgono gli stessi ragionamenti dei precedenti per cui il modello migliore è quello con i termini quadratici e l’assenza delle variabili non significative (mod4_n). Il valore dell’R2 però, rispetto al mod4 aumenta e quello di RMSE diminuisce.
r2_4 <- r2_adj[4]
r2_4n <- r2_adj_n[4]
RMSE_4 <- rmse[4]
RMSE_4n <- rmse_n[4]
kable(data.frame("modello" = c("mod4", "mod4_n"),
"R2_adj" = c(r2_4, r2_4n),
"RSME" = c(RMSE_4, RMSE_4n))) %>%
kable_styling(full_width = FALSE, position = 'left')
| modello | R2_adj | RSME |
|---|---|---|
| mod4 | 0.7389825 | 267.7584 |
| mod4_n | 0.7423658 | 265.8425 |
Si riverificano i VIF per la multicollinearità e si confermano i valori alti per i termini quadratici.
vif_4 <- vif(mod4_n)
vif_df <- data.frame(VIF = vif_4)
kable(vif_df) %>%
kable_styling(full_width = FALSE, position = 'left')
| VIF | |
|---|---|
| N.gravidanze | 1.026105 |
| Gestazione | 537.633834 |
| Lunghezza | 491.627198 |
| Cranio | 1.674221 |
| Tipo.parto | 1.003751 |
| Sesso | 1.048273 |
| I(Gestazione^2) | 509.008354 |
| I(Lunghezza^2) | 464.302191 |
Si calcola la distanza di cook per questo modello:
cook_n<-cooks.distance(mod4_n)
plot(cook_n, ylim = c(0,1))
text(x = 500, y = 0.8,
labels = paste("Max cook distance:", round(max(cook_n), 2)),
, col = "blue", cex = 0.8)
Questa volta nessun valore anomalo influenza le stime del modello di regressione.
Si effettuano nuovamente i test stastici sui residui e si confrontano con i risultati precedenti
res_sh_n <- shapiro.test(residuals(mod4_n))
res_bp_n <- lmtest::bptest(mod4_n)
res_dw_n <- lmtest::dwtest(mod4_n)
res_test_results_n <-
data.frame(
Test = c("Shapiro-Wilk", "Breusch-Pagan", "Durbin-Watson"),
Caratteristica_testata = c("Normalità", "Omoschedasticità", "Autocorrelazione"),
p_value_mod4n = c(format(res_sh_n$p.value, scientific = T, digits = 3), round(res_bp_n$p.value, 3), round(res_dw_n$p.value, 3)),
p_value_mod4 = res_test_results$p_value
)
kable(res_test_results_n)%>%
kable_styling(full_width = FALSE, position = 'left')
| Test | Caratteristica_testata | p_value_mod4n | p_value_mod4 |
|---|---|---|---|
| Shapiro-Wilk | Normalità | 8.65e-12 | 8.11e-13 |
| Breusch-Pagan | Omoschedasticità | 0.031 | 5.79e-18 |
| Durbin-Watson | Autocorrelazione | 0.103 | 0.098 |
I test per i residui danno gli stessi risultati precedenti, anche se l’autocorrelazione e l’omoschedasticità risultano migliorati in termini di significatività, soprattutto l’omoschedasticità.
Si prova ad effettuare una trasformazione sulla variabile y (peso) per vedere se l’analisi dei residui migliora
model_box <- boxcox(mod4_n)
La lambda ottimale risulta essere 0.4646465.
lambda <- model_box$x[which.max(model_box$y)]
lambda
[1] 0.4646465
Si trasforma la variabile peso con la lambda trovata e si costruisce un nuovo modello di regressione, dipendente dalle stesse variabili selezionate precedentemente, con la variabile peso trasformata.
df_2$peso_trans <- (df_2$Peso^lambda - 1) / lambda
mod_bc <- lm(peso_trans ~ N.gravidanze + Gestazione + Lunghezza + Cranio + Tipo.parto + Sesso + I(Gestazione^2) + I(Lunghezza^2), data = df_2)
summary(mod_bc)
Call:
lm(formula = peso_trans ~ N.gravidanze + Gestazione + Lunghezza +
Cranio + Tipo.parto + Sesso + I(Gestazione^2) + I(Lunghezza^2),
data = df_2)
Residuals:
Min 1Q Median 3Q Max
-15.6298 -2.3001 -0.0706 2.1534 19.0174
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -9.344e+01 1.182e+01 -7.903 4.04e-15 ***
N.gravidanze 1.812e-01 5.527e-02 3.279 0.00106 **
Gestazione 4.183e+00 8.670e-01 4.825 1.49e-06 ***
Lunghezza 4.039e-02 5.942e-02 0.680 0.49669
Cranio 1.334e-01 5.509e-03 24.211 < 2e-16 ***
Tipo.partoNat 3.509e-01 1.541e-01 2.278 0.02284 *
SessoM 9.523e-01 1.431e-01 6.656 3.44e-11 ***
I(Gestazione^2) -4.782e-02 1.136e-02 -4.209 2.66e-05 ***
I(Lunghezza^2) 1.105e-04 6.051e-05 1.826 0.06799 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 3.493 on 2490 degrees of freedom
Multiple R-squared: 0.7709, Adjusted R-squared: 0.7702
F-statistic: 1047 on 8 and 2490 DF, p-value: < 2.2e-16
Si osserva un aumento dell’R2 aggiustato, tuttavia si perde la significatività di alcune variabili come la lunghezza.
Inoltre, i test sui residui continuano a non passare:
res_sh_bc <- shapiro.test(residuals(mod_bc))
res_bp_bc <- lmtest::bptest(mod_bc)
res_dw_bc <- lmtest::dwtest(mod_bc)
res_test_results_bc <-
data.frame(
Test = c("Shapiro-Wilk", "Breusch-Pagan", "Durbin-Watson"),
Caratteristica_testata = c("Normalità", "Omoschedasticità", "Autocorrelazione"),
p_value_modbc = c(format(res_sh_bc$p.value, scientific = T, digits = 3), round(res_bp_bc$p.value, 3), round(res_dw_bc$p.value, 3)),
p_value_mod4n = res_test_results_n$p_value_mod4n,
p_value_mod4 = res_test_results$p_value
)
kable(res_test_results_bc)%>%
kable_styling(full_width = FALSE, position = 'left')
| Test | Caratteristica_testata | p_value_modbc | p_value_mod4n | p_value_mod4 |
|---|---|---|---|---|
| Shapiro-Wilk | Normalità | 9.43e-10 | 8.65e-12 | 8.11e-13 |
| Breusch-Pagan | Omoschedasticità | 0.001 | 0.031 | 5.79e-18 |
| Durbin-Watson | Autocorrelazione | 0.095 | 0.103 | 0.098 |
In base alle analisi fatte si decide di utilizzare il modello 4 ottenuto dopo la rimozione dell’outlier (mod4_n). Nonostante, infatti, i test statistici non passino, dai grafici diagnostici si possono osservare solo alcune deviazioni dalla normalità sulle code della distribuzione, mentre la distribuzione centrale appare conforme. Inoltre i grafici relativi ad omoschedasticità, distribuzione attorno alla media e leverage non evidenziano anomalie. Anche i valori outlier e leverage risultano avere tutti distanza di cook inferiore a 1 e pertanto non influenzano significativamente le stime della regressione.
Il modello finale è dunque il seguente
mod4_n$call
lm(formula = df_2$Peso ~ N.gravidanze + Gestazione + Lunghezza +
Cranio + Tipo.parto + Sesso + I(Gestazione^2) + I(Lunghezza^2),
data = df_2)
Si rimuove dal dataset la variabile che era stata aggiunta con il peso trasformato
df_2$peso_trans <- NULL
Si stima, con il modello scelto, il peso di una neonata considerando una madre alla terza gravidanza (N.gravidanze =2) che partorirà alla 39esima settimana. Per le variabili non citate, ma presenti nel modello, si utilizza il valore medio per quelle quantitative (Lunghezza e Cranio) e la moda per quella qualitativa (Tipo.Parto).
mean_lunghezza <- mean(df_2$Lunghezza)
mean_cranio <- mean(df_2$Cranio)
mode_tipoparto <- names(sort(table(df_2$Tipo.parto), decreasing = TRUE))[1]
newdata <- data.frame(
N.gravidanze = 2,
Gestazione = 39,
Lunghezza = mean_lunghezza,
Cranio = mean_cranio,
Tipo.parto = factor(mode_tipoparto, levels = levels(df_2$Tipo.parto)),
Sesso = factor("F", levels = levels(df_2$Sesso))
)
predict(mod4_n, newdata = newdata)
1
3257.494
Il valore di peso predetto è 3257.494 g.
Si osserva ora la dipendenza del peso dalla gestazione in base al sesso e in base al tipo di parto.
g1 <-
ggplot(data=df_2)+
geom_point(aes(x=Gestazione,
y=Peso,
col=Sesso),position = "jitter")+
geom_smooth(aes(x=Gestazione,
y=Peso,
col=Sesso),se=F,method = "lm")+
geom_smooth(aes(x=Gestazione,
y=Peso), col="black", se=F, method=lm)
g2 <-
ggplot(data=df_2)+
geom_point(aes(x=Gestazione,
y=Peso,
col=Tipo.parto),position = "jitter")+
geom_smooth(aes(x=Gestazione,
y=Peso,
col=Tipo.parto),se=F,method = "lm")+
geom_smooth(aes(x=Gestazione,
y=Peso), col="black", se=F, method=lm)
g1+g2
Si può osservare come in media i neonati maschi abbiano sempre peso
maggiore delle neonate femmine.
Relativamente al tipo di parto si osserva invece come esso influenzi il peso del nascituro principalmente sui parti inferiori alle 37 settimane, dove il parto cesareo porta mediamente a neonati con peso maggiore. Invece per un numero di settimane di gestazione superiore a 37 le rette di regressione vanno quasi a coincidere, ad indicare che il tipo di parto perde di influenza.
Si osserva ora la dipendenza del peso dalla lunghezza e dalle dimensioni del cranio del neonato.
g1<-
ggplot(data=df_2)+
geom_point(aes(x=Lunghezza,
y=Peso,
col=Sesso),position = "jitter")+
geom_smooth(aes(x=Lunghezza,
y=Peso,
col=Sesso),se=F,method = "lm")+
geom_smooth(aes(x=Lunghezza,
y=Peso), col="black", se=F, method=lm)
g2 <-
ggplot(data=df_2)+
geom_point(aes(x=Cranio,
y=Peso,
col=Sesso),position = "jitter")+
geom_smooth(aes(x=Cranio,
y=Peso,
col=Sesso),se=F,method = "lm")+
geom_smooth(aes(x=Cranio,
y=Peso), col="black", se=F, method=lm)
g1+g2
Si osserva la forte dipendenza del peso dalle caratteristiche
antropometriche del neonato.
Si osserva questa dipendenza anche con un grafico 3D.
scatter3d(Peso~Lunghezza + Cranio, point.col = Sesso, groups=Sesso, axis.col = c("black", "black", "black"), residuals=FALSE, surface.alpha=0.3)
rglwidget()
Si osserva anche il grafico 3D con le variabili Gestazione e N.Gravidanze.
scatter3d(Peso~Gestazione + N.gravidanze, point.col = Sesso, groups=Sesso, axis.col = c("black", "black", "black"), surface.alpha=0.3, residuals=FALSE)
rglwidget()
Si può osservare la dipendenza del peso dalla variabile Gestazione, mentre non se ne osserva una rispetto al numero di gravidanze. Tuttavia la visualizzazione grafica non tiene conto del fatto che in realtà il modello include anche tutte le altre variabili che non sono incluse nel grafico, pertanto la significatività del numero di gravidanze potrebbe non essere direttamente visualizzabile con poche variabili.
È stato sviluppato un modello di regressione in grado di spiegare il 74% della variabilità del peso neonatale e di prevedere il peso dei neonati a partire dalle informazioni sulla madre e sulla gravidanza. In particolare, il peso risulta molto dipendente dalle caratteristiche antropometriche del neonato, dal numero di settimane di gestazione e dal numero di gravidanze pregresse della madre. Il modello sviluppato è il seguente:
summary(mod4_n)
Call:
lm(formula = df_2$Peso ~ N.gravidanze + Gestazione + Lunghezza +
Cranio + Tipo.parto + Sesso + I(Gestazione^2) + I(Lunghezza^2),
data = df_2)
Residuals:
Min 1Q Median 3Q Max
-1168.71 -179.48 -11.03 161.56 1312.24
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -2.879e+03 9.015e+02 -3.194 0.001422 **
N.gravidanze 1.465e+01 4.214e+00 3.477 0.000516 ***
Gestazione 2.009e+02 6.611e+01 3.038 0.002403 **
Lunghezza -1.910e+01 4.531e+00 -4.216 2.58e-05 ***
Cranio 1.006e+01 4.200e-01 23.951 < 2e-16 ***
Tipo.partoNat 2.829e+01 1.175e+01 2.409 0.016087 *
SessoM 7.338e+01 1.091e+01 6.727 2.14e-11 ***
I(Gestazione^2) -2.143e+00 8.664e-01 -2.474 0.013437 *
I(Lunghezza^2) 3.078e-02 4.614e-03 6.671 3.12e-11 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 266.3 on 2490 degrees of freedom
Multiple R-squared: 0.7432, Adjusted R-squared: 0.7424
F-statistic: 900.7 on 8 and 2490 DF, p-value: < 2.2e-16
Si possono fare le seguenti osservazioni:
Inoltre si è osservato con lo studio del dataset e del modello di regressione che i neonati maschi hanno un peso medio maggiore delle neonate femmine e che, per settimane di gestazione inferiori a circa 37, il parto cesareo in media porta a nascite con peso inferiore rispetto a quello naturale.