# Carica le librerie necessarie
library(tidyverse) # ggplot2 è incluso in tidyverse
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.0.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(caret) # Per machine learning e analisi statistica
## Caricamento del pacchetto richiesto: lattice
##
## Caricamento pacchetto: 'caret'
##
## Il seguente oggetto è mascherato da 'package:purrr':
##
## lift
library(ggplot2) # Per la creazione di grafici
library(car) # Per l'analisi di regressione
## Caricamento del pacchetto richiesto: carData
##
## Caricamento pacchetto: 'car'
##
## Il seguente oggetto è mascherato da 'package:dplyr':
##
## recode
##
## Il seguente oggetto è mascherato da 'package:purrr':
##
## some
library(lmtest) # Per il test di ipotesi nei modelli
## Caricamento del pacchetto richiesto: zoo
##
## Caricamento pacchetto: 'zoo'
##
## I seguenti oggetti sono mascherati da 'package:base':
##
## as.Date, as.Date.numeric
library(knitr) # Per l'integrazione di risultati nel documento
library(conflicted)
conflict_prefer("filter", "dplyr")
## [conflicted] Will prefer dplyr::filter over any other package.
conflict_prefer("lag", "dplyr")
## [conflicted] Will prefer dplyr::lag over any other package.
conflict_prefer("recode", "dplyr")
## [conflicted] Will prefer dplyr::recode over any other package.
# Carica il dataset in formato CSV
dataset <- read.csv("C:/Users/carbaren/Desktop/R/neonati.csv")
# Verifica i nomi delle colonne del dataset
colnames(dataset)
## [1] "Anni.madre" "N.gravidanze" "Fumatrici" "Gestazione" "Peso"
## [6] "Lunghezza" "Cranio" "Tipo.parto" "Ospedale" "Sesso"
# Mostra le prime righe del dataset
head(dataset)
## 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
# Statistiche descrittive più complete per avere un'idea generale del dataset
summary(dataset)
## 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
##
##
##
sapply(dataset, function(x) c(mean = mean(x, na.rm = TRUE),
sd = sd(x, na.rm = TRUE),
median = median(x, na.rm = TRUE)))
## Warning in mean.default(x, na.rm = TRUE): l'argomento non è numerico o logico:
## si restituisce NA
## Warning in var(if (is.vector(x) || is.factor(x)) x else as.double(x), na.rm =
## na.rm): NA introdotti per coercizione
## Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]):
## l'argomento non è numerico o logico: si restituisce NA
## Warning in mean.default(x, na.rm = TRUE): l'argomento non è numerico o logico:
## si restituisce NA
## Warning in var(if (is.vector(x) || is.factor(x)) x else as.double(x), na.rm =
## na.rm): NA introdotti per coercizione
## Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]):
## l'argomento non è numerico o logico: si restituisce NA
## Warning in mean.default(x, na.rm = TRUE): l'argomento non è numerico o logico:
## si restituisce NA
## Warning in var(if (is.vector(x) || is.factor(x)) x else as.double(x), na.rm =
## na.rm): NA introdotti per coercizione
## Warning in mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]):
## l'argomento non è numerico o logico: si restituisce NA
## Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza
## mean 28.164000 0.981200 0.0416000 38.980400 3284.0808 494.69200
## sd 5.273578 1.280587 0.1997133 1.868639 525.0387 26.31864
## median 28.000000 1.000000 0.0000000 39.000000 3300.0000 500.00000
## Cranio Tipo.parto Ospedale Sesso
## mean 340.02920 NA NA NA
## sd 16.42533 NA NA NA
## median 340.00000 NA NA NA
# Verifica la presenza di valori mancanti nel dataset
sapply(dataset, function(x) sum(is.na(x)))
## Anni.madre N.gravidanze Fumatrici Gestazione Peso Lunghezza
## 0 0 0 0 0 0
## Cranio Tipo.parto Ospedale Sesso
## 0 0 0 0
# Controllo per età madre improbabili
table(dataset$Anni.madre)
##
## 0 1 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
## 1 1 1 2 6 13 18 24 45 66 74 100 115 131 180 184 197 172 174 200
## 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
## 147 159 110 96 66 64 41 38 27 19 13 8 2 4 1 1
dataset$Anni.madre[dataset$Anni.madre < 15 | dataset$Anni.madre > 60] <- NA
# Imputazione dei valori mancanti con la media per le variabili numeriche
dataset_imputed <- dataset %>%
mutate(across(where(is.numeric), ~ifelse(is.na(.), mean(., na.rm = TRUE), .)))
# Creazione della distribuzione del peso del neonato
ggplot(dataset_imputed, aes(x = Peso)) +
geom_histogram(binwidth = 50, fill = "blue", color = "black") +
theme_minimal() +
labs(title = "Distribuzione del peso del neonato")

# Distribuzione della durata della gravidanza
ggplot(dataset_imputed, aes(x = Gestazione)) +
geom_histogram(binwidth = 1, fill = "green", color = "black") +
theme_minimal() +
labs(title = "Distribuzione della durata della gravidanza")

# Creiamo una tabella delle frequenze tra ospedale e tipo di parto
hospital_parto_cesareo <- table(dataset_imputed$Ospedale, dataset_imputed$Tipo.parto)
hospital_parto_cesareo
##
## Ces Nat
## osp1 242 574
## osp2 254 595
## osp3 232 603
# Eseguiamo un test chi-quadrato per verificare se la distribuzione del tipo di parto dipende dall'ospedale
chisq.test(hospital_parto_cesareo)
##
## Pearson's Chi-squared test
##
## data: hospital_parto_cesareo
## X-squared = 1.0972, df = 2, p-value = 0.5778
# Test t per verificare se il peso è significativamente diverso dalla media della popolazione (3200g)
t.test(dataset_imputed$Peso, mu = 3200)
##
## One Sample t-test
##
## data: dataset_imputed$Peso
## t = 8.0071, df = 2499, p-value = 1.782e-15
## alternative hypothesis: true mean is not equal to 3200
## 95 percent confidence interval:
## 3263.490 3304.672
## sample estimates:
## mean of x
## 3284.081
# Test t per verificare se la lunghezza è significativamente diversa dalla media della popolazione (50 cm)
t.test(dataset_imputed$Lunghezza, mu = 50)
##
## One Sample t-test
##
## data: dataset_imputed$Lunghezza
## t = 844.82, df = 2499, p-value < 2.2e-16
## alternative hypothesis: true mean is not equal to 50
## 95 percent confidence interval:
## 493.6598 495.7242
## sample estimates:
## mean of x
## 494.692
# Matrice di correlazione per le variabili predittive
cor(dataset_imputed %>% select(Peso, Anni.madre, N.gravidanze, Gestazione, Lunghezza, Cranio))
## Peso Anni.madre N.gravidanze Gestazione Lunghezza
## Peso 1.00000000 -0.02403702 0.00240730 0.5917687 0.79603676
## Anni.madre -0.02403702 1.00000000 0.38335003 -0.1361348 -0.06634028
## N.gravidanze 0.00240730 0.38335003 1.00000000 -0.1014919 -0.06040371
## Gestazione 0.59176872 -0.13613476 -0.10149194 1.0000000 0.61892045
## Lunghezza 0.79603676 -0.06634028 -0.06040371 0.6189204 1.00000000
## Cranio 0.70480151 0.01786895 0.03900707 0.4608289 0.60334097
## Cranio
## Peso 0.70480151
## Anni.madre 0.01786895
## N.gravidanze 0.03900707
## Gestazione 0.46082894
## Lunghezza 0.60334097
## Cranio 1.00000000
# Creazione di un modello di regressione lineare con diverse variabili predittive
modello <- lm(Peso ~ Anni.madre + N.gravidanze + Fumatrici + Gestazione + Lunghezza + Cranio + Tipo.parto + Ospedale + Sesso, data = dataset_imputed)
# Riepilogo del modello per ottenere informazioni sui coefficienti e significatività
summary(modello)
##
## Call:
## lm(formula = Peso ~ Anni.madre + N.gravidanze + Fumatrici + Gestazione +
## Lunghezza + Cranio + Tipo.parto + Ospedale + Sesso, data = dataset_imputed)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1123.41 -181.25 -14.88 160.77 2612.63
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6735.4798 141.4534 -47.616 < 2e-16 ***
## Anni.madre 0.8074 1.1521 0.701 0.4835
## N.gravidanze 11.4050 4.6661 2.444 0.0146 *
## Fumatrici -30.1408 27.5397 -1.094 0.2739
## Gestazione 32.5308 3.8182 8.520 < 2e-16 ***
## Lunghezza 10.2956 0.3007 34.239 < 2e-16 ***
## Cranio 10.4713 0.4261 24.573 < 2e-16 ***
## Tipo.partoNat 29.5056 12.0847 2.442 0.0147 *
## Ospedaleosp2 -11.2377 13.4391 -0.836 0.4031
## Ospedaleosp3 28.1091 13.4967 2.083 0.0374 *
## SessoM 77.5355 11.1781 6.936 5.11e-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
# Selezione del modello passo per passo (stepwise) escludendo variabili irrilevanti come Tipo.parto e Ospedale
modello_selezionato <- step(modello, direction = "both")
## 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 36851 186809099 28074
## - Fumatrici 1 89883 186862131 28075
## <none> 186772248 28075
## - Tipo.parto 1 447324 187219571 28079
## - N.gravidanze 1 448298 187220546 28079
## - Ospedale 2 687324 187459572 28081
## - Sesso 1 3610391 190382639 28121
## - Gestazione 1 5446911 192219158 28145
## - Cranio 1 45311010 232083258 28616
## - Lunghezza 1 87967488 274739735 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 36851 186772248 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 37866 186862131 28075
## - Tipo.parto 1 440684 187340680 28077
## - Ospedale 2 701680 187601677 28079
## - 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
# Riepilogo del modello ottimale
summary(modello_selezionato)
##
## Call:
## lm(formula = Peso ~ N.gravidanze + Gestazione + Lunghezza + Cranio +
## Tipo.parto + Ospedale + Sesso, data = dataset_imputed)
##
## 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
# Calcoliamo i criteri AIC e BIC per il modello selezionato
AIC(modello_selezionato)
## [1] 35169.79
BIC(modello_selezionato)
## [1] 35228.03
# Calcoliamo il valore di R² per valutare la bontà di adattamento del modello
rsq <- summary(modello_selezionato)$r.squared
cat("R²:", rsq)
## R²: 0.7286934
# Calcoliamo il RMSE (Root Mean Squared Error) per valutare la qualità del modello
pred <- predict(modello_selezionato)
# Calcoliamo i residui
residui <- dataset_imputed$Peso - pred
# Calcoliamo il RMSE
rmse <- sqrt(mean(residui^2))
# Visualizza il valore del RMSE
cat("RMSE:", rmse)
## RMSE: 273.4227
# Diagnosi dei residui per verificare eventuali pattern non catturati dal modello
plot(residui, main = "Residui del modello", xlab = "Indice dei dati", ylab = "Residui")
abline(h = 0, col = "red")

# Distribuzione dei residui
hist(residui, main = "Distribuzione dei residui", xlab = "Residui", col = "gray", border = "black")

# Calcolo del VIF (Variance Inflation Factor) per verificare la multicollinearità
vif(modello_selezionato)
## GVIF Df GVIF^(1/(2*Df))
## N.gravidanze 1.025244 1 1.012544
## Gestazione 1.670237 1 1.292376
## Lunghezza 2.081921 1 1.442886
## Cranio 1.626507 1 1.275346
## Tipo.parto 1.003872 1 1.001934
## Ospedale 1.003038 2 1.000759
## Sesso 1.040337 1 1.019969
# Creazione di un nuovo dato per la previsione
nuovo_dato <- data.frame(
Anni.madre = 28,
N.gravidanze = 3,
Fumatrici = 0,
Gestazione = 39,
Lunghezza = 50,
Cranio = 34,
Tipo.parto = "Nat", # Esempio: "Nat" per parto naturale
Ospedale = "osp1", # Esempio: "osp1" per ospedale 1
Sesso = "M" # Sesso: "M" per maschio
)
# Assicuriamoci che le variabili categoriche siano trattate correttamente come fattori
nuovo_dato$Tipo.parto <- factor(nuovo_dato$Tipo.parto, levels = levels(dataset_imputed$Tipo.parto))
nuovo_dato$Ospedale <- factor(nuovo_dato$Ospedale, levels = levels(dataset_imputed$Ospedale))
nuovo_dato$Sesso <- factor(nuovo_dato$Sesso, levels = levels(dataset_imputed$Sesso))
# Previsione del peso del neonato per il nuovo caso
previsione <- predict(modello_selezionato, nuovo_dato)
# Stampa il risultato
cat("Il peso previsto del neonato è:", previsione, "grammi")
## Il peso previsto del neonato è: NA grammi
# Creiamo un grafico per visualizzare l'effetto della durata della gravidanza sul peso
ggplot(dataset_imputed, aes(x = Gestazione, y = Peso)) +
geom_point() +
geom_smooth(method = "lm", color = "blue") +
labs(title = "Impatto della durata della gravidanza sul peso del neonato",
x = "Durata della gravidanza (settimane)",
y = "Peso del neonato (grammi)")
## `geom_smooth()` using formula = 'y ~ x'

# Creiamo un boxplot per visualizzare l'effetto del fumo sul peso
ggplot(dataset_imputed, aes(x = Fumatrici, y = Peso, fill = factor(Fumatrici))) +
geom_boxplot() +
labs(title = "Differenze nel peso tra fumatrice e non fumatrice")
