data <- read.csv("neonati.csv", stringsAsFactors = FALSE)
head(data)
## Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza Cranio Tipo.parto
## 1 26 0 0 42 3380 490 325 Nat
## 2 21 2 0 39 3150 490 345 Nat
## 3 34 3 0 38 3640 500 375 Nat
## 4 28 1 0 41 3690 515 365 Nat
## 5 20 0 0 38 3700 480 335 Nat
## 6 32 0 0 40 3200 495 340 Nat
## Ospedale Sesso
## 1 osp3 M
## 2 osp1 F
## 3 osp2 M
## 4 osp2 M
## 5 osp3 F
## 6 osp2 F
str(data)
## '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(data)
## 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
##
##
##
colSums(is.na(data))
## Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza
## 0 0 0 0 0 0
## Cranio Tipo.parto Ospedale Sesso
## 0 0 0 0
sum(duplicated(data))
## [1] 0
library(corrplot)
## Warning: il pacchetto 'corrplot' è stato creato con R versione 4.4.2
## corrplot 0.95 loaded
boxplot(data$Anni.madre, main = "Boxplot Età della Madre")
hist(data$Peso, main = "Istogramma Peso Neonati", xlab = "Peso (g)", breaks = 30)
corrplot(cor(data[, sapply(data, is.numeric)]), method = "color")
cor(data[, sapply(data, is.numeric)])
## Anni.madre N.gravidanze Fumatrici Gestazione Peso
## Anni.madre 1.000000000 0.38063184 0.006057852 -0.13566714 -0.02247017
## N.gravidanze 0.380631844 1.00000000 0.046869466 -0.10149194 0.00240730
## Fumatrici 0.006057852 0.04686947 1.000000000 0.03220907 -0.01894534
## Gestazione -0.135667143 -0.10149194 0.032209066 1.00000000 0.59176872
## Peso -0.022470167 0.00240730 -0.018945344 0.59176872 1.00000000
## Lunghezza -0.063491571 -0.06040371 -0.020781411 0.61892045 0.79603676
## Cranio 0.016076703 0.03900707 -0.008665549 0.46082894 0.70480151
## Lunghezza Cranio
## Anni.madre -0.06349157 0.016076703
## N.gravidanze -0.06040371 0.039007074
## Fumatrici -0.02078141 -0.008665549
## Gestazione 0.61892045 0.460828941
## Peso 0.79603676 0.704801507
## Lunghezza 1.00000000 0.603340974
## Cranio 0.60334097 1.000000000
table(data$Fumatrici)
##
## 0 1
## 2396 104
table(data$Tipo.parto)
##
## Ces Nat
## 728 1772
table(data$Ospedale)
##
## osp1 osp2 osp3
## 816 849 835
table(data$Sesso)
##
## F M
## 1256 1244
data <- data[data$Anni.madre > 0, ]
data$Fumatrici <- factor(data$Fumatrici)
data$Tipo.parto <- factor(data$Tipo.parto)
data$Ospedale <- factor(data$Ospedale)
data$Sesso <- factor(data$Sesso)
data$Prematuro <- ifelse(data$Gestazione < 37, 1, 0)
Dopo aver importato il set ed aver effettuato l’EDA, ho applicato alcune modifiche per rendere il dataset più attendibile. Ho rimosso i dati delle madri con età = 0 e ho convertito le variabili categoriche in fattori, ho anche creato una nuova colonna che ci indichi i parti prematuri (quelli avvenuti prima della 37esima settimana)
boxplot(data$Peso ~ data$Fumatrici,
main = "Peso Neonati vs Fumo Materno",
xlab = "Fumatrici", ylab = "Peso (g)")
plot(data$Gestazione, data$Peso,
main = "Peso Neonati vs Settimane di Gestazione",
xlab = "Settimane di Gestazione", ylab = "Peso (g)", pch = 19)
Dai grafici possiamo dedurre che: Il peso mediano dei neonati è leggermente inferiore nel gruppo delle madri fumatrici; Nel gruppo delle madri fumatrici ci sono più outlier sul lato inferiore, ad indicare la presenza di più neonati con un peso più basso; La variabilità del peso è simile tra i due gruppi, ma la distribuzione per le madri fumatrici sembra più compressa verso i valori inferiori.
Per le settimane di gestazione si nota una relazione positiva e il peso del neonato. Più lunga è la durata della gestazione e maggiore è il peso mediano del neonato; I neonati prematuri tendono ad avere un peso significativamente inferirore rispetto ai neonati a termine; C’è una variabilità marcata nei pesi dei neonati anche a durate di gestazione simili, ciò potrebbe indicare che altre variabili possono influenzare il peso dei neonati.
cont_table_ospedale_parto <- table(data$Ospedale, data$Tipo.parto)
test_chi_ospedale_parto <- chisq.test(cont_table_ospedale_parto)
test_chi_ospedale_parto
##
## Pearson's Chi-squared test
##
## data: cont_table_ospedale_parto
## X-squared = 1.0604, df = 2, p-value = 0.5885
Poiché il p-value è maggiore di 0.05, non rifiutiamo l’ipotesi nulla. Questo significa che non ci sono prove sufficienti per affermare che ci siano differenze significative nel numero di parti cesarei tra i diversi ospedali.
In base ai dati a disposizione, possiamo concludere che la distribuzione dei parti cesarei sembra indipendente dall’ospedale. Non ci sono evidenze che in alcuni ospedali si facciano significativamente più parti cesarei rispetto ad altri.
media_peso_campione <- mean(data$Peso)
media_lunghezza_campione <- mean(data$Lunghezza)
media_peso_popolazione <- 3300
media_lunghezza_popolazione <- 50
test_peso <- t.test(data$Peso, mu = media_peso_popolazione)
test_lunghezza <- t.test(data$Lunghezza, mu = media_lunghezza_popolazione)
test_peso
##
## One Sample t-test
##
## data: data$Peso
## t = -1.5069, df = 2498, p-value = 0.132
## alternative hypothesis: true mean is not equal to 3300
## 95 percent confidence interval:
## 3263.572 3304.769
## sample estimates:
## mean of x
## 3284.17
test_lunghezza
##
## One Sample t-test
##
## data: data$Lunghezza
## t = 844.49, df = 2498, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 50
## 95 percent confidence interval:
## 493.6613 495.7265
## sample estimates:
## mean of x
## 494.6939
Per il peso: Non c’è una differenza significativa rispetto alla popolazione. Per la lunghezza: La differenza rispetto alla popolazione è altamente significativa.
t.test(data$Peso ~ data$Sesso)
##
## Welch Two Sample t-test
##
## data: data$Peso by data$Sesso
## t = -12.116, df = 2490, 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.3966 -207.3302
## sample estimates:
## mean in group F mean in group M
## 3161.132 3408.496
t.test(data$Lunghezza ~ data$Sesso)
##
## Welch Two Sample t-test
##
## data: data$Lunghezza by data$Sesso
## t = -9.5864, df = 2459, p-value < 2.2e-16
## alternative hypothesis: true difference in means between group F and group M is not equal to 0
## 95 percent confidence interval:
## -11.937899 -7.883398
## sample estimates:
## mean in group F mean in group M
## 489.7643 499.6750
t.test(data$Cranio ~ data$Sesso)
##
## Welch Two Sample t-test
##
## data: data$Cranio by data$Sesso
## t = -7.4237, df = 2490.6, p-value = 1.555e-13
## alternative hypothesis: true difference in means between group F and group M is not equal to 0
## 95 percent confidence interval:
## -6.100260 -3.550953
## sample estimates:
## mean in group F mean in group M
## 337.6330 342.4586
In tutti e tre i test (Peso, Lunghezza, e Cranio), la differenza tra i sessi è statisticamente significativa, con le femmine che tendono ad avere valori medi inferiori per ciascuna delle misure rispetto ai maschi. Pertanto, possiamo rifiutare l’ipotesi nulla di assenza di differenze tra i gruppi per tutte e tre le variabili.
library(car)
## Warning: il pacchetto 'car' è stato creato con R versione 4.4.2
## Caricamento del pacchetto richiesto: carData
## Warning: il pacchetto 'carData' è stato creato con R versione 4.4.2
modello_base <- lm(Peso ~ ., data = data)
vif(modello_base)
## GVIF Df GVIF^(1/(2*Df))
## Anni.madre 1.188698 1 1.090274
## N.gravidanze 1.187004 1 1.089497
## Fumatrici 1.008263 1 1.004123
## Gestazione 2.475330 1 1.573318
## Lunghezza 2.097481 1 1.448268
## Cranio 1.637117 1 1.279499
## Tipo.parto 1.005089 1 1.002541
## Ospedale 1.004573 2 1.001141
## Sesso 1.043444 1 1.021491
## Prematuro 1.978516 1 1.406597
library(caret)
## Warning: il pacchetto 'caret' è stato creato con R versione 4.4.2
## Caricamento del pacchetto richiesto: ggplot2
## Caricamento del pacchetto richiesto: lattice
set.seed(123)
index <- createDataPartition(data$Peso, p = 0.8, list = FALSE)
trainData <- data[index, ]
testData <- data[-index, ]
dim(trainData)
## [1] 2002 11
dim(testData)
## [1] 497 11
modello_base <- lm(Peso ~ Anni.madre + N.gravidanze + Fumatrici + Gestazione +
Lunghezza + Cranio + Tipo.parto + Ospedale + Sesso + Prematuro,
data = trainData)
summary(modello_base)
##
## Call:
## lm(formula = Peso ~ Anni.madre + N.gravidanze + Fumatrici + Gestazione +
## Lunghezza + Cranio + Tipo.parto + Ospedale + Sesso + Prematuro,
## data = trainData)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1054.8 -183.0 -15.2 163.1 2538.0
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6485.7414 208.7668 -31.067 < 2e-16 ***
## Anni.madre 1.4693 1.2964 1.133 0.257
## N.gravidanze 8.7847 5.3436 1.644 0.100
## Fumatrici1 -47.1189 30.2905 -1.556 0.120
## Gestazione 29.6231 5.1926 5.705 1.34e-08 ***
## Lunghezza 9.9393 0.3424 29.025 < 2e-16 ***
## Cranio 10.5968 0.4822 21.977 < 2e-16 ***
## Tipo.partoNat 21.2799 13.6579 1.558 0.119
## Ospedaleosp2 -17.7828 15.2651 -1.165 0.244
## Ospedaleosp3 16.5139 15.3140 1.078 0.281
## SessoM 81.4633 12.6628 6.433 1.56e-10 ***
## Prematuro -42.4878 35.1832 -1.208 0.227
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 278.1 on 1990 degrees of freedom
## Multiple R-squared: 0.723, Adjusted R-squared: 0.7215
## F-statistic: 472.3 on 11 and 1990 DF, p-value: < 2.2e-16
library(MASS)
modello_migliorato <- stepAIC(lm(Peso ~ Anni.madre + N.gravidanze + Fumatrici +
Gestazione + Lunghezza + Cranio +
Tipo.parto + Ospedale + Sesso + Prematuro,
data = trainData),
direction = "both")
## Start: AIC=22545.89
## Peso ~ Anni.madre + N.gravidanze + Fumatrici + Gestazione + Lunghezza +
## Cranio + Tipo.parto + Ospedale + Sesso + Prematuro
##
## Df Sum of Sq RSS AIC
## - Anni.madre 1 99323 153965952 22545
## - Prematuro 1 112759 153979387 22545
## <none> 153866629 22546
## - Fumatrici 1 187099 154053727 22546
## - Tipo.parto 1 187700 154054329 22546
## - N.gravidanze 1 208961 154075590 22547
## - Ospedale 2 396537 154263166 22547
## - Gestazione 1 2516398 156383026 22576
## - Sesso 1 3200050 157066679 22585
## - Cranio 1 37343233 191209862 22979
## - Lunghezza 1 65138056 219004685 23251
##
## Step: AIC=22545.18
## Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio +
## Tipo.parto + Ospedale + Sesso + Prematuro
##
## Df Sum of Sq RSS AIC
## - Prematuro 1 115766 154081718 22545
## <none> 153965952 22545
## - Tipo.parto 1 187202 154153155 22546
## - Fumatrici 1 189259 154155211 22546
## + Anni.madre 1 99323 153866629 22546
## - Ospedale 2 401307 154367259 22546
## - N.gravidanze 1 396645 154362597 22548
## - Gestazione 1 2446080 156412033 22575
## - Sesso 1 3206093 157172045 22584
## - Cranio 1 37738255 191704207 22982
## - Lunghezza 1 65111070 219077022 23249
##
## Step: AIC=22544.69
## Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio +
## Tipo.parto + Ospedale + Sesso
##
## Df Sum of Sq RSS AIC
## <none> 154081718 22545
## - Tipo.parto 1 178746 154260463 22545
## - Fumatrici 1 180941 154262659 22545
## + Prematuro 1 115766 153965952 22545
## + Anni.madre 1 102330 153979387 22545
## - Ospedale 2 400916 154482634 22546
## - N.gravidanze 1 402861 154484579 22548
## - Sesso 1 3164929 157246647 22583
## - Gestazione 1 4524189 158605907 22601
## - Cranio 1 38010568 192092286 22984
## - Lunghezza 1 66004807 220086525 23257
summary(modello_migliorato)
##
## Call:
## lm(formula = Peso ~ N.gravidanze + Fumatrici + Gestazione + Lunghezza +
## Cranio + Tipo.parto + Ospedale + Sesso, data = trainData)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1048.85 -184.66 -14.21 162.65 2557.36
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6603.9460 151.7161 -43.528 < 2e-16 ***
## N.gravidanze 11.2314 4.9214 2.282 0.0226 *
## Fumatrici1 -46.3162 30.2828 -1.529 0.1263
## Gestazione 32.6533 4.2696 7.648 3.16e-14 ***
## Lunghezza 9.9714 0.3413 29.212 < 2e-16 ***
## Cranio 10.6584 0.4808 22.168 < 2e-16 ***
## Tipo.partoNat 20.7570 13.6545 1.520 0.1286
## Ospedaleosp2 -17.9422 15.2578 -1.176 0.2398
## Ospedaleosp3 16.5392 15.3008 1.081 0.2799
## SessoM 80.9567 12.6561 6.397 1.97e-10 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 278.1 on 1992 degrees of freedom
## Multiple R-squared: 0.7226, Adjusted R-squared: 0.7214
## F-statistic: 576.7 on 9 and 1992 DF, p-value: < 2.2e-16
predictions <- predict(modello_migliorato, newdata = testData)
rmse <- sqrt(mean((testData$Peso - predictions)^2))
mae <- mean(abs(testData$Peso - predictions))
sst <- sum((testData$Peso - mean(testData$Peso))^2)
sse <- sum((testData$Peso - predictions)^2)
r2 <- 1 - (sse / sst)
cat("RMSE:", rmse, "\n")
## RMSE: 257.7244
cat("MAE:", mae, "\n")
## MAE: 200.7319
cat("R-squared:", r2, "\n")
## R-squared: 0.752335
residui <- testData$Peso - predictions
par(mfrow = c(2, 2))
plot(predictions, residui, main = "Residui vs Predetti", xlab = "Predetti", ylab = "Residui")
abline(h = 0, col = "red")
hist(residui, main = "Istogramma dei Residui", xlab = "Residui", breaks = 30)
qqnorm(residui, main = "QQ-Plot dei Residui")
qqline(residui, col = "red")
plot(testData$Peso, predictions, main = "Valori Osservati vs Predetti",
xlab = "Osservati", ylab = "Predetti")
abline(0, 1, col = "blue")
par(mfrow = c(1, 1))
In questa fase del progetto ho creato il modello base e poi quello migliorato con l’AIC. ###
new_data <- data.frame(
Anni.madre = c(30, 28, 35, 32, 40),
N.gravidanze = c(3, 1, 2, 4, 2),
Fumatrici = factor(c("0", "1", "0", "0", "1"), levels = levels(trainData$Fumatrici)),
Gestazione = c(39, 40, 38, 37, 41),
Lunghezza = c(480, 472, 518, 490, 505),
Cranio = c(335, 364, 403, 384, 346),
Tipo.parto = factor(c("Nat", "Ces", "Nat", "Nat", "Ces"), levels = levels(trainData$Tipo.parto)),
Ospedale = factor(c("osp2", "osp1", "osp3", "osp2", "osp3"), levels = levels(trainData$Ospedale)),
Sesso = factor(c("F", "M", "M", "F", "M"), levels = levels(trainData$Sesso))
)
previsioni <- predict(modello_migliorato, newdata = new_data)
new_data$Predizione_Peso <- previsioni
print(previsioni)
## 1 2 3 4 5
## 3062.870 3334.209 4238.108 3630.771 3531.837
print(new_data)
## Anni.madre N.gravidanze Fumatrici Gestazione Lunghezza Cranio Tipo.parto
## 1 30 3 0 39 480 335 Nat
## 2 28 1 1 40 472 364 Ces
## 3 35 2 0 38 518 403 Nat
## 4 32 4 0 37 490 384 Nat
## 5 40 2 1 41 505 346 Ces
## Ospedale Sesso Predizione_Peso
## 1 osp2 F 3062.870
## 2 osp1 M 3334.209
## 3 osp3 M 4238.108
## 4 osp2 F 3630.771
## 5 osp3 M 3531.837
Con il modello migliorato sono state effettuate alcune previsioni su dati casuali ottendo risultati attendibili.
library(ggplot2)
ggplot(trainData, aes(x = Gestazione, y = Peso)) +
geom_point(aes(color = "Real Data"), alpha = 0.6) +
geom_smooth(method = "lm", aes(color = "Fitted Line"), se = FALSE, linetype = "dashed") +
labs(title = "Relazione tra Gestazione e Peso", x = "Settimane di Gestazione", y = "Peso (grammi)") +
theme_minimal() +
scale_color_manual(values = c("Real Data" = "blue", "Fitted Line" = "red"))
## `geom_smooth()` using formula = 'y ~ x'
ggplot(trainData, aes(x = factor(Fumatrici), y = Peso, fill = factor(Fumatrici))) +
geom_boxplot() +
labs(title = "Distribuzione del Peso in base al Fumo", x = "Fumatrici (0 = No, 1 = Sì)", y = "Peso (grammi)") +
scale_fill_manual(values = c("0" = "lightblue", "1" = "lightcoral")) +
theme_minimal()
trainData$predictions <- predict(modello_migliorato, newdata = trainData)
ggplot(trainData, aes(x = Peso, y = predictions)) +
geom_point(alpha = 0.6, color = "blue") +
geom_smooth(method = "lm", color = "red", se = FALSE) +
labs(title = "Confronto tra Valori Reali e Previsioni", x = "Peso Reale (grammi)", y = "Peso Predetto (grammi)") +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
importance <- varImp(modello_migliorato, scale = FALSE)
ggplot(importance, aes(x = reorder(rownames(importance), Overall), y = Overall)) +
geom_bar(stat = "identity", fill = "steelblue") +
coord_flip() +
labs(title = "Importanza delle Variabili nel Modello", x = "Variabile", y = "Importanza") +
theme_minimal()