df = read.csv("C:/Users/johan/Downloads/diabetes.csv", sep=",", header=TRUE, fileEncoding = "UTF-8")
Pregnancies
: Número de embarazos.Glucose
: Concentración de glucosa.BloodPressure
: Presión arterial diastólica.SkinThickness
: Grosor del pliegue cutáneo del
tríceps.Insulin
: Insulina sérica.BMI
: Índice de masa corporal (peso en kg / (altura en
m)^2).DiabetesPedigreeFunction
: Una función que pondera
genéticamente el riesgo de diabetes en relación con la historia
familiar.Age
: Edad del paciente.Outcome
: La variable de resultado, donde 1 indica que
el paciente tiene diabetes y 0 indica que no la tiene.suppressWarnings({
require(dplyr)
require(tibble)
library(pracma)
require(stringr)
require(ggplot2)
require(ggpubr)
require(e1071)
require(psych)
library(reshape2)
library(Hmisc)
library(Amelia)
library(mice)
library(foreign)
library(ggplot2)
library(gridExtra)
library(hrbrthemes)
library(outliers)
library(ggplot2)
library(dplyr)
library(psych)
library(reshape2)
library(GGally)
library(factoextra)
library(EnvStats)
library(tidyr)
})
## Cargando paquete requerido: dplyr
##
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
## Cargando paquete requerido: tibble
## Cargando paquete requerido: stringr
## Cargando paquete requerido: ggplot2
## Cargando paquete requerido: ggpubr
## Cargando paquete requerido: e1071
##
## Adjuntando el paquete: 'e1071'
## The following object is masked from 'package:pracma':
##
## sigmoid
## Cargando paquete requerido: psych
##
## Adjuntando el paquete: 'psych'
## The following objects are masked from 'package:ggplot2':
##
## %+%, alpha
## The following objects are masked from 'package:pracma':
##
## logit, polar
##
## Adjuntando el paquete: 'Hmisc'
## The following object is masked from 'package:psych':
##
## describe
## The following object is masked from 'package:e1071':
##
## impute
## The following object is masked from 'package:pracma':
##
## ceil
## The following objects are masked from 'package:dplyr':
##
## src, summarize
## The following objects are masked from 'package:base':
##
## format.pval, units
## Cargando paquete requerido: Rcpp
## ##
## ## Amelia II: Multiple Imputation
## ## (Version 1.8.3, built: 2024-11-07)
## ## Copyright (C) 2005-2025 James Honaker, Gary King and Matthew Blackwell
## ## Refer to http://gking.harvard.edu/amelia/ for more information
## ##
##
## Adjuntando el paquete: 'mice'
## The following object is masked from 'package:stats':
##
## filter
## The following objects are masked from 'package:base':
##
## cbind, rbind
##
## Adjuntando el paquete: 'gridExtra'
## The following object is masked from 'package:dplyr':
##
## combine
##
## Adjuntando el paquete: 'outliers'
## The following object is masked from 'package:psych':
##
## outlier
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
##
## Adjuntando el paquete: 'EnvStats'
## The following object is masked from 'package:Hmisc':
##
## stripChart
## The following objects are masked from 'package:e1071':
##
## kurtosis, skewness
## The following objects are masked from 'package:stats':
##
## predict, predict.lm
## The following object is masked from 'package:base':
##
## print.default
##
## Adjuntando el paquete: 'tidyr'
## The following object is masked from 'package:reshape2':
##
## smiths
Mostramos las primeras y ultimas filas de la base de datos para ver como esta estructurado.
## Pregnancies Glucose BloodPressure SkinThickness Insulin BMI
## 1 6 148 72 35 0 33.6
## 2 1 85 66 29 0 26.6
## 3 8 183 64 0 0 23.3
## 4 1 89 66 23 94 28.1
## 5 0 137 40 35 168 43.1
## 6 5 116 74 0 0 25.6
## DiabetesPedigreeFunction Age Outcome
## 1 0.627 50 1
## 2 0.351 31 0
## 3 0.672 32 1
## 4 0.167 21 0
## 5 2.288 33 1
## 6 0.201 30 0
## Pregnancies Glucose BloodPressure SkinThickness Insulin BMI
## 763 9 89 62 0 0 22.5
## 764 10 101 76 48 180 32.9
## 765 2 122 70 27 0 36.8
## 766 5 121 72 23 112 26.2
## 767 1 126 60 0 0 30.1
## 768 1 93 70 31 0 30.4
## DiabetesPedigreeFunction Age Outcome
## 763 0.142 33 0
## 764 0.171 63 0
## 765 0.340 27 0
## 766 0.245 30 0
## 767 0.349 47 1
## 768 0.315 23 0
Ahora analizaremos la naturaleza de las variables de nuestra base de datos.
## Rows: 768
## Columns: 9
## $ Pregnancies <int> 6, 1, 8, 1, 0, 5, 3, 10, 2, 8, 4, 10, 10, 1, …
## $ Glucose <int> 148, 85, 183, 89, 137, 116, 78, 115, 197, 125…
## $ BloodPressure <int> 72, 66, 64, 66, 40, 74, 50, 0, 70, 96, 92, 74…
## $ SkinThickness <int> 35, 29, 0, 23, 35, 0, 32, 0, 45, 0, 0, 0, 0, …
## $ Insulin <int> 0, 0, 0, 94, 168, 0, 88, 0, 543, 0, 0, 0, 0, …
## $ BMI <dbl> 33.6, 26.6, 23.3, 28.1, 43.1, 25.6, 31.0, 35.…
## $ DiabetesPedigreeFunction <dbl> 0.627, 0.351, 0.672, 0.167, 2.288, 0.201, 0.2…
## $ Age <int> 50, 31, 32, 21, 33, 30, 26, 29, 53, 54, 30, 3…
## $ Outcome <int> 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, …
Vemos que tenemos 9 columnas de variables con 768 observaciones, de las cuales 7 columnas son de tipo entero y 2 de tipo decimal.
Reemplazaremos los valores 0.0 por Na para luego realizar el tratamiento de estos datos.
df$Glucose[df$Glucose == 0.0] <- NA
df$BloodPressure[df$BloodPressure == 0.0] <- NA
df$SkinThickness[df$SkinThickness == 0.0] <- NA
df$Insulin[df$Insulin == 0.0] <- NA
df$BMI[df$BMI == 0.0] <- NA
Calculamos el número de valores faltantes para cada variable del DataFrame.
## Pregnancies Glucose BloodPressure
## 0 5 35
## SkinThickness Insulin BMI
## 227 374 11
## DiabetesPedigreeFunction Age Outcome
## 0 0 0
## Pregnancies Glucose BloodPressure
## 0.0000000 0.6510417 4.5572917
## SkinThickness Insulin BMI
## 29.5572917 48.6979167 1.4322917
## DiabetesPedigreeFunction Age Outcome
## 0.0000000 0.0000000 0.0000000
Vemos que la variable Glucose
tiene 5 datos faltantes,
Bloodpressure
tiene 35, SkinThickness
tiene
227, Insulin
tiene 374 y BMI
tiene 11 datos
faltantes. Estos equivalen a un 9% de datos faltantes del total de
datos.
Vamos a realizar la imputación de los datos usando diversas tecnicas.
Las variables a las que le vamos a aplicar las tecnicas de imputacion son las siguientes:
SkinThickness
: 29.55 % de datos faltantesInsulin
: 48.69 % de datos faltantesGlucose
: 0.65 % de datos faltantesBloodPressure
: 4.55 % de datos faltantesBMI
: 1.43 % de datos faltantesGuardamos el dataframe original y verificamos sus distribuciones para luego compararlos con los nuevos datos.
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df$Pregnancies
##
## Test Statistic: W = 0.9042813
##
## P-value: 1.609257e-21
Vemos que el p-valor es menor que el nivel de significancia (0.05), por lo que la variable no tiene una distribución normal.
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df$Glucose
##
## Test Statistic: W = 0.9696409
##
## P-value: 1.720326e-11
Vemos que el p-valor es menor que el nivel de significancia (0.05), por lo que la variable no tiene una distribución normal.
# BloodPressure
shapiro_bloodpressure <- shapiro.test(df$BloodPressure)
print(shapiro_bloodpressure)
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df$BloodPressure
##
## Test Statistic: W = 0.9903145
##
## P-value: 9.45138e-05
Vemos que el p-valor es menor que el nivel de significancia (0.05), por lo que la variable no tiene una distribución normal.
# SkinThickness
shapiro_skinthickness <- shapiro.test(df$SkinThickness)
print(shapiro_skinthickness)
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df$SkinThickness
##
## Test Statistic: W = 0.9679992
##
## P-value: 1.775691e-09
Vemos que el p-valor es menor que el nivel de significancia (0.05), por lo que la variable no tiene una distribución normal.
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df$Insulin
##
## Test Statistic: W = 0.8040996
##
## P-value: 1.698218e-21
Vemos que el p-valor es menor que el nivel de significancia (0.05), por lo que la variable no tiene una distribución normal.
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df$BMI
##
## Test Statistic: W = 0.9795543
##
## P-value: 8.557785e-09
Vemos que el p-valor es menor que el nivel de significancia (0.05), por lo que la variable no tiene una distribución normal.
# DiabetesPedigreeFunction
shapiro_dpf <- shapiro.test(df$DiabetesPedigreeFunction)
print(shapiro_dpf)
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df$DiabetesPedigreeFunction
##
## Test Statistic: W = 0.8365181
##
## P-value: 2.477506e-27
Vemos que el p-valor es menor que el nivel de significancia (0.05), por lo que la variable no tiene una distribución normal.
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df$Age
##
## Test Statistic: W = 0.8747669
##
## P-value: 2.402274e-24
Vemos que el p-valor es menor que el nivel de significancia (0.05), por lo que la variable no tiene una distribución normal.
Todas nuestras variables coinciden en que no siguen una distribución normal.
Este metodo reemplaza los valores faltantes con valores observados que son similares en términos de predicción, manteniendo la coherencia y la distribución original de los datos. Este enfoque es especialmente útil para evitar imputaciones irreales y preservar las características estadísticas del conjunto de datos.
mostramos nuevamente la tabla para ver como se ven las primeras filas
de SKinThickess
y Insulin
## Pregnancies Glucose BloodPressure SkinThickness Insulin BMI
## 1 6 148 72 35 NA 33.6
## 2 1 85 66 29 NA 26.6
## 3 8 183 64 NA NA 23.3
## 4 1 89 66 23 94 28.1
## 5 0 137 40 35 168 43.1
## 6 5 116 74 NA NA 25.6
## DiabetesPedigreeFunction Age Outcome
## 1 0.627 50 1
## 2 0.351 31 0
## 3 0.672 32 1
## 4 0.167 21 0
## 5 2.288 33 1
## 6 0.201 30 0
Aplicamos ahora el metodo de imputación por emparejamiento predictivo medio.
imp <- mice(df, m=5, maxit=50, method ='pmm', seed=500, printFlag = FALSE)
df_pmm <- complete(imp, 1)
Luego de aplicado este metodo, vamos a ver las primeras filas del dataset ya imputado para comprobar que no tenemos NA
## Pregnancies Glucose BloodPressure SkinThickness Insulin BMI
## 1 6 148 72 35 83 33.6
## 2 1 85 66 29 55 26.6
## 3 8 183 64 20 175 23.3
## 4 1 89 66 23 94 28.1
## 5 0 137 40 35 168 43.1
## 6 5 116 74 24 175 25.6
## DiabetesPedigreeFunction Age Outcome
## 1 0.627 50 1
## 2 0.351 31 0
## 3 0.672 32 1
## 4 0.167 21 0
## 5 2.288 33 1
## 6 0.201 30 0
## Pregnancies Glucose BloodPressure
## 0 0 0
## SkinThickness Insulin BMI
## 0 0 0
## DiabetesPedigreeFunction Age Outcome
## 0 0 0
Con el Comando Colsums
comprobamos que se aplico el
metodo de forma correcta, obteniendo 0 datos faltantes en cada
variable.
SkinThickness
mantuvo o no la
distribución, esto lo verificaremos luego con una prueba.suppressWarnings({
ggp1 <- ggplot(data.frame(value=previo_df$SkinThickness), aes(x=value)) +
geom_histogram(fill="#FBD000", color="#E52521", alpha=0.9) +
ggtitle("Original") +
xlab('SkinThickness') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
ggp2 <- ggplot(data.frame(value=df_pmm$SkinThickness), aes(x=value)) +
geom_histogram(fill="#43B047", color="#049CD8", alpha=0.9) +
ggtitle("Imputación") +
xlab('SkinThickness') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
grid.arrange(ggp1, ggp2, ncol = 2)
})
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df_pmm$SkinThickness
##
## Test Statistic: W = 0.9731303
##
## P-value: 1.121809e-10
Visualmente parece que la distribución no se afecto, esto lo comprobaremos con una prueba no parametrica debido a que el p-valor es menor que (0.05).
SkinThickness
- PMMPara evaluar si la imputación mantuvo la forma original de la distribución de las variables, se emplea la prueba de Kolmogorov–Smirnov, la cual permite comparar estadísticamente dos muestras y determinar si provienen de la misma distribución.
Hipótesis nula: ambas muestras provienen de la misma distribución.
Hipótesis alternativa: las muestras provienen de distribuciones diferentes.
##
## Asymptotic two-sample Kolmogorov-Smirnov test
##
## data: previo_df$SkinThickness and df_pmm$SkinThickness
## D = 0.017481, p-value = 1
## alternative hypothesis: two-sided
Como el p-valor es mayor que el nivel de significancia, no hay evidencia significativa para rechazar H_0, por lo que ambas muestras provienen de la misma distribución.
Insulin
, estos es, un histograma para verificar
inicialmente de forma grafica si nuestra imputación afecto o no la
distribución, esto lo verificaremos luego con una prueba.suppressWarnings({
ggp3 <- ggplot(data.frame(value=previo_df$Insulin), aes(x=value)) +
geom_histogram(fill="#FBD000", color="#E52521", alpha=0.9) +
ggtitle("Original") +
xlab('Insulin') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
ggp4 <- ggplot(data.frame(value=df_pmm$Insulin), aes(x=value)) +
geom_histogram(fill="#43B047", color="#049CD8", alpha=0.9) +
ggtitle("Imputación") +
xlab('Insulin') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
grid.arrange(ggp3, ggp4, ncol = 2)
})
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df_pmm$Insulin
##
## Test Statistic: W = 0.7981324
##
## P-value: 7.952825e-30
Visualmente parece que la distribución no se afecto, esto lo comprobaremos con una prueba no paramétrica debido a que el p-valor es menor que (0.05).
Insulin
- PMMPara evaluar si la imputación mantuvo la forma original de la distribución de las variables, se emplea la prueba de Kolmogorov–Smirnov, la cual permite comparar estadísticamente dos muestras y determinar si provienen de la misma distribución.
Hipótesis nula: ambas muestras provienen de la misma distribución.
Hipótesis alternativa: las muestras provienen de distribuciones diferentes.
##
## Asymptotic two-sample Kolmogorov-Smirnov test
##
## data: previo_df$Insulin and df_pmm$Insulin
## D = 0.034218, p-value = 0.9206
## alternative hypothesis: two-sided
Como el p-valor es mayor que el nivel de significancia, no hay evidencia significativa para rechazar H_0, por lo que ambas muestras provienen de la misma distribución.
Este método utiliza un modelo de regresión lineal para predecir los valores faltantes. Para cada variable con datos faltantes, se ajusta un modelo de regresión lineal que usa las otras variables del conjunto de datos como predictores.
mostramos nuevamente la tabla para ver como se ven las primeras filas
de SKinThickess
y Insulin
## Pregnancies Glucose BloodPressure SkinThickness Insulin BMI
## 1 6 148 72 35 NA 33.6
## 2 1 85 66 29 NA 26.6
## 3 8 183 64 NA NA 23.3
## 4 1 89 66 23 94 28.1
## 5 0 137 40 35 168 43.1
## 6 5 116 74 NA NA 25.6
## DiabetesPedigreeFunction Age Outcome
## 1 0.627 50 1
## 2 0.351 31 0
## 3 0.672 32 1
## 4 0.167 21 0
## 5 2.288 33 1
## 6 0.201 30 0
Aplicamos ahora el metodo de norm.predict
imp_norm <- mice(df, m=5, maxit=50, method = 'norm.predict', seed = 500, printFlag = FALSE)
df_norm_predict <- complete(imp_norm, 1)
Luego de aplicado este método, vamos a ver las primeras filas del dataset ya imputado para comprobar que no tenemos NA
## Pregnancies Glucose BloodPressure SkinThickness Insulin BMI
## 1 6 148 72 35.00000 220.41825 33.6
## 2 1 85 66 29.00000 69.60061 26.6
## 3 8 183 64 21.44380 256.23203 23.3
## 4 1 89 66 23.00000 94.00000 28.1
## 5 0 137 40 35.00000 168.00000 43.1
## 6 5 116 74 21.87459 117.51189 25.6
## DiabetesPedigreeFunction Age Outcome
## 1 0.627 50 1
## 2 0.351 31 0
## 3 0.672 32 1
## 4 0.167 21 0
## 5 2.288 33 1
## 6 0.201 30 0
## Pregnancies Glucose BloodPressure
## 0 0 0
## SkinThickness Insulin BMI
## 0 0 0
## DiabetesPedigreeFunction Age Outcome
## 0 0 0
Con el Comando Colsums
comprobamos que se aplico el
metodo de forma correcta, obteniendo 0 datos faltantes en cada
variable.
SkinThickness
mantuvo o no la
distribución, esto lo verificaremos luego con una prueba.suppressWarnings({
ggp1 <- ggplot(data.frame(value=previo_df$SkinThickness), aes(x=value)) +
geom_histogram(fill="#FBD000", color="#E52521", alpha=0.9) +
ggtitle("Original") +
xlab('SkinThickness') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
ggp2 <- ggplot(data.frame(value=df_norm_predict$SkinThickness), aes(x=value)) +
geom_histogram(fill="#43B047", color="#049CD8", alpha=0.9) +
ggtitle("Imputación") +
xlab('SkinThickness') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
grid.arrange(ggp1, ggp2, ncol = 2)
})
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df_norm_predict$SkinThickness
##
## Test Statistic: W = 0.9709169
##
## P-value: 3.126631e-11
Visualmente parece que la distribución no se afecto, esto lo comprobaremos con una prueba no paramétrica debido a que el p-valor es menor que (0.05).
SkinThickness
-
Norm.predictPara evaluar si la imputación mantuvo la forma original de la distribución de las variables, se emplea la prueba de Kolmogorov–Smirnov, la cual permite comparar estadísticamente dos muestras y determinar si provienen de la misma distribución.
Hipótesis nula: ambas muestras provienen de la misma distribución.
Hipótesis alternativa: las muestras provienen de distribuciones diferentes.
##
## Asymptotic two-sample Kolmogorov-Smirnov test
##
## data: previo_df$SkinThickness and df_norm_predict$SkinThickness
## D = 0.045395, p-value = 0.53
## alternative hypothesis: two-sided
Como el p-valor es mayor que el nivel de significancia, no hay evidencia significativa para rechazar H_0, por lo que ambas muestras provienen de la misma distribución.
Insulin
, estos es, un histograma para verificar
inicialmente de forma grafica si nuestra imputación afecto o no la
distribución. Esto lo verificaremos luego con una prueba.suppressWarnings({
ggp3 <- ggplot(data.frame(value=previo_df$Insulin), aes(x=value)) +
geom_histogram(fill="#FBD000", color="#E52521", alpha=0.9) +
ggtitle("Original") +
xlab('Insulin') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
ggp4 <- ggplot(data.frame(value=df_norm_predict$Insulin), aes(x=value)) +
geom_histogram(fill="#43B047", color="#049CD8", alpha=0.9) +
ggtitle("Imputación") +
xlab('Insulin') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
grid.arrange(ggp3, ggp4, ncol = 2)
})
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df_norm_predict$Insulin
##
## Test Statistic: W = 0.8478726
##
## P-value: 1.654757e-26
Visualmente parece que la distribución no se afecto, esto lo comprobaremos con una prueba no paramétrica debido a que el p-valor es menor que (0.05).
Insulin
- Norm.predictPara evaluar si la imputación mantuvo la forma original de la distribución de las variables, se emplea la prueba de Kolmogorov–Smirnov, la cual permite comparar estadísticamente dos muestras y determinar si provienen de la misma distribución.
Hipótesis nula: ambas muestras provienen de la misma distribución.
Hipótesis alternativa: las muestras provienen de distribuciones diferentes.
##
## Asymptotic two-sample Kolmogorov-Smirnov test
##
## data: previo_df$Insulin and df_norm_predict$Insulin
## D = 0.064212, p-value = 0.2332
## alternative hypothesis: two-sided
Como el p-valor es mayor que el nivel de significancia, no hay evidencia significativa para rechazar H_0, por lo que ambas muestras provienen de la misma distribución.
Este método utiliza un modelo de regresión lineal para predecir los valores faltantes. La principal diferencia con norm.predict es que norm.nob agrega un residuo aleatorio a cada valor predicho. Este residuo se extrae de la distribución de los residuos del modelo de regresión.
mostramos nuevamente la tabla para ver como se ven las primeras filas
de SKinThickess
y Insulin
## Pregnancies Glucose BloodPressure SkinThickness Insulin BMI
## 1 6 148 72 35 NA 33.6
## 2 1 85 66 29 NA 26.6
## 3 8 183 64 NA NA 23.3
## 4 1 89 66 23 94 28.1
## 5 0 137 40 35 168 43.1
## 6 5 116 74 NA NA 25.6
## DiabetesPedigreeFunction Age Outcome
## 1 0.627 50 1
## 2 0.351 31 0
## 3 0.672 32 1
## 4 0.167 21 0
## 5 2.288 33 1
## 6 0.201 30 0
Aplicamos ahora el metodo de norm.nob
imp_norm_nob <- mice(df, m=5, maxit=50, method = 'norm.nob', seed = 500, printFlag = FALSE)
df_norm_nob <- complete(imp_norm_nob, 1)
Luego de aplicado este método, vamos a ver las primeras filas del dataset ya imputado para comprobar que no tenemos NA.
## Pregnancies Glucose BloodPressure SkinThickness Insulin BMI
## 1 6 148 72 35.00000 282.7451 33.6
## 2 1 85 66 29.00000 130.6682 26.6
## 3 8 183 64 10.33126 253.1314 23.3
## 4 1 89 66 23.00000 94.0000 28.1
## 5 0 137 40 35.00000 168.0000 43.1
## 6 5 116 74 20.24396 -130.7138 25.6
## DiabetesPedigreeFunction Age Outcome
## 1 0.627 50 1
## 2 0.351 31 0
## 3 0.672 32 1
## 4 0.167 21 0
## 5 2.288 33 1
## 6 0.201 30 0
## Pregnancies Glucose BloodPressure
## 0 0 0
## SkinThickness Insulin BMI
## 0 0 0
## DiabetesPedigreeFunction Age Outcome
## 0 0 0
Con el Comando Colsums
comprobamos que se aplico el
metodo de forma correcta, obteniendo 0 datos faltantes en cada
variable.
SkinThickness
mantuvo o no la
distribución, esto lo verificaremos luego con una prueba.suppressWarnings({
ggp1 <- ggplot(data.frame(value=previo_df$SkinThickness), aes(x=value)) +
geom_histogram(fill="#FBD000", color="#E52521", alpha=0.9) +
ggtitle("Original") +
xlab('SkinThickness') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
ggp2 <- ggplot(data.frame(value=df_norm_nob$SkinThickness), aes(x=value)) +
geom_histogram(fill="#43B047", color="#049CD8", alpha=0.9) +
ggtitle("Imputación") +
xlab('SkinThickness') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
grid.arrange(ggp1, ggp2, ncol = 2)
})
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df_norm_nob$SkinThickness
##
## Test Statistic: W = 0.9790628
##
## P-value: 4.944505e-09
Visualmente parece que la distribución no se afecto, esto lo comprobaremos con una prueba no paramétrica debido a que el p-valor es menor que (0.05).
SkinThickness
- Norm.nobPara evaluar si la imputación mantuvo la forma original de la distribución de las variables, se emplea la prueba de Kolmogorov–Smirnov, la cual permite comparar estadísticamente dos muestras y determinar si provienen de la misma distribución.
Hipótesis nula: ambas muestras provienen de la misma distribución.
Hipótesis alternativa: las muestras provienen de distribuciones diferentes.
##
## Asymptotic two-sample Kolmogorov-Smirnov test
##
## data: previo_df$SkinThickness and df_norm_nob$SkinThickness
## D = 0.028725, p-value = 0.9559
## alternative hypothesis: two-sided
Como el p-valor es mayor que el nivel de significancia, no hay evidencia significativa para rechazar H_0, por lo que ambas muestras provienen de la misma distribución.
Insulin
, estos es, un histograma para verificar
inicialmente de forma grafica si nuestra imputación afecto o no la
distribución. esto lo verificaremos luego con una prueba.suppressWarnings({
ggp3 <- ggplot(data.frame(value=previo_df$Insulin), aes(x=value)) +
geom_histogram(fill="#FBD000", color="#E52521", alpha=0.9) +
ggtitle("Original") +
xlab('Insulin') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
ggp4 <- ggplot(data.frame(value=df_norm_nob$Insulin), aes(x=value)) +
geom_histogram(fill="#43B047", color="#049CD8", alpha=0.9) +
ggtitle("Imputación") +
xlab('Insulin') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
grid.arrange(ggp3, ggp4, ncol = 2)
})
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df_norm_nob$Insulin
##
## Test Statistic: W = 0.9274439
##
## P-value: 8.41167e-19
Visualmente parece que la distribución no se afecto, esto lo comprobaremos con una prueba no paramétrica debido a que el p-valor es menor que (0.05).
Insulin
- Norm.nobPara evaluar si la imputación mantuvo la forma original de la distribución de las variables, se emplea la prueba de Kolmogorov–Smirnov, la cual permite comparar estadísticamente dos muestras y determinar si provienen de la misma distribución.
Hipótesis nula: ambas muestras provienen de la misma distribución.
Hipótesis alternativa: las muestras provienen de distribuciones diferentes.
##
## Asymptotic two-sample Kolmogorov-Smirnov test
##
## data: previo_df$Insulin and df_norm_nob$Insulin
## D = 0.06324, p-value = 0.2487
## alternative hypothesis: two-sided
Como el p-valor es mayor que el nivel de significancia, no hay evidencia significativa para rechazar H_0, por lo que ambas muestras provienen de la misma distribución.
Este método utiliza un modelo de regresión lineal para predecir los valores faltantes. La diferencia principal es cómo genera ese error. Mientras norm.nob usa los residuos del modelo de regresión, norm usa un método de “muestreo bayesiano” para la distribución de los parámetros del modelo.
Mostramos nuevamente la tabla para ver como se ven las primeras filas
de SKinThickess
y Insulin
del dataset
original.
## Pregnancies Glucose BloodPressure SkinThickness Insulin BMI
## 1 6 148 72 35 NA 33.6
## 2 1 85 66 29 NA 26.6
## 3 8 183 64 NA NA 23.3
## 4 1 89 66 23 94 28.1
## 5 0 137 40 35 168 43.1
## 6 5 116 74 NA NA 25.6
## DiabetesPedigreeFunction Age Outcome
## 1 0.627 50 1
## 2 0.351 31 0
## 3 0.672 32 1
## 4 0.167 21 0
## 5 2.288 33 1
## 6 0.201 30 0
Aplicamos ahora el metodo de norm.nob
imp_norm <- mice(df, m=5, maxit=50, method = 'norm', seed = 500, printFlag = FALSE)
df_norm <- complete(imp_norm, 1)
Luego de aplicado este método, vamos a ver las primeras filas del dataset ya imputado para comprobar que no tenemos NA.
## Pregnancies Glucose BloodPressure SkinThickness Insulin BMI
## 1 6 148 72 35.00000 456.01723 33.6
## 2 1 85 66 29.00000 60.66381 26.6
## 3 8 183 64 16.75604 186.58545 23.3
## 4 1 89 66 23.00000 94.00000 28.1
## 5 0 137 40 35.00000 168.00000 43.1
## 6 5 116 74 23.76877 299.81798 25.6
## DiabetesPedigreeFunction Age Outcome
## 1 0.627 50 1
## 2 0.351 31 0
## 3 0.672 32 1
## 4 0.167 21 0
## 5 2.288 33 1
## 6 0.201 30 0
## Pregnancies Glucose BloodPressure
## 0 0 0
## SkinThickness Insulin BMI
## 0 0 0
## DiabetesPedigreeFunction Age Outcome
## 0 0 0
Con el Comando Colsums
comprobamos que se aplico el
metodo de forma correcta, obteniendo 0 datos faltantes en cada
variable.
SkinThickness
mantuvo o no la
distribución, esto lo verificaremos luego con una prueba.suppressWarnings({
ggp1 <- ggplot(data.frame(value=previo_df$SkinThickness), aes(x=value)) +
geom_histogram(fill="#FBD000", color="#E52521", alpha=0.9) +
ggtitle("Original") +
xlab('SkinThickness') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
ggp2 <- ggplot(data.frame(value=df_norm$SkinThickness), aes(x=value)) +
geom_histogram(fill="#43B047", color="#049CD8", alpha=0.9) +
ggtitle("Imputación") +
xlab('SkinThickness') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
grid.arrange(ggp1, ggp2, ncol = 2)
})
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df_norm_nob$SkinThickness
##
## Test Statistic: W = 0.9790628
##
## P-value: 4.944505e-09
Visualmente parece que la distribución no se afecto, esto lo comprobaremos con una prueba no paramétrica debido a que el p-valor es menor que (0.05).
SkinThickness
- NormPara evaluar si la imputación mantuvo la forma original de la distribución de las variables, se emplea la prueba de Kolmogorov–Smirnov, la cual permite comparar estadísticamente dos muestras y determinar si provienen de la misma distribución.
Hipótesis nula: ambas muestras provienen de la misma distribución.
Hipótesis alternativa: las muestras provienen de distribuciones diferentes.
##
## Asymptotic two-sample Kolmogorov-Smirnov test
##
## data: previo_df$SkinThickness and df_norm$SkinThickness
## D = 0.033031, p-value = 0.8792
## alternative hypothesis: two-sided
Como el p-valor es mayor que el nivel de significancia, no hay evidencia significativa para rechazar H_0, por lo que ambas muestras provienen de la misma distribución.
Insulin
, estos es, un histograma para verificar
inicialmente de forma grafica si nuestra imputación afecto o no la
distribución. esto lo verificaremos luego con una prueba.suppressWarnings({
ggp3 <- ggplot(data.frame(value=previo_df$Insulin), aes(x=value)) +
geom_histogram(fill="#FBD000", color="#E52521", alpha=0.9) +
ggtitle("Original") +
xlab('Insulin') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
ggp4 <- ggplot(data.frame(value=df_norm$Insulin), aes(x=value)) +
geom_histogram(fill="#43B047", color="#049CD8", alpha=0.9) +
ggtitle("Imputación") +
xlab('Insulin') + ylab('Frequency') +
theme_ipsum() +
theme(plot.title = element_text(size=15))
grid.arrange(ggp3, ggp4, ncol = 2)
})
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
##
## Results of Hypothesis Test
## --------------------------
##
## Alternative Hypothesis:
##
## Test Name: Shapiro-Wilk normality test
##
## Data: df_norm_nob$Insulin
##
## Test Statistic: W = 0.9274439
##
## P-value: 8.41167e-19
Visualmente parece que la distribución no se afecto, esto lo comprobaremos con una prueba no paramétrica debido a que el p-valor es menor que (0.05).
Insulin
- NormPara evaluar si la imputación mantuvo la forma original de la distribución de las variables, se emplea la prueba de Kolmogorov–Smirnov, la cual permite comparar estadísticamente dos muestras y determinar si provienen de la misma distribución.
Hipótesis nula: ambas muestras provienen de la misma distribución.
Hipótesis alternativa: las muestras provienen de distribuciones diferentes.
##
## Asymptotic two-sample Kolmogorov-Smirnov test
##
## data: previo_df$Insulin and df_norm$Insulin
## D = 0.067147, p-value = 0.1909
## alternative hypothesis: two-sided
Como el p-valor es mayor que el nivel de significancia, no hay evidencia significativa para rechazar H_0, por lo que ambas muestras provienen de la misma distribución.
Los analisis de datos atipicos y el eda lo voy a realizar con la base de datos que se encuentra imputada con la tecnica PMM debido a que los datos no tienen distribucion normal, y en este caso PMM se adapta mejor porque no hace suposiciones sobre la distribución de la variable y utiliza valores reales del dataset, a diferencia de las demas porque estos otros metodos utilizan regresión lineal y tienden a imputar valores que se ajustan a una distribución normal, lo que es un problema debido a que tiende a cambiar la forma de la distribución aunque verificamos y todas mantienen la distribución.
En esta sección vamos a identificar los valores atipicos de las variables de la base de datos utilizando las tecnicas que aprendimos en clase.
Resumen descriptivo inicial para identificar outliers en los datos.
## Pregnancies Glucose BloodPressure SkinThickness
## Min. : 0.000 Min. : 44.0 Min. : 24.00 Min. : 7.00
## 1st Qu.: 1.000 1st Qu.: 99.0 1st Qu.: 64.00 1st Qu.:21.00
## Median : 3.000 Median :117.0 Median : 72.00 Median :29.00
## Mean : 3.845 Mean :121.7 Mean : 72.42 Mean :28.82
## 3rd Qu.: 6.000 3rd Qu.:141.0 3rd Qu.: 80.00 3rd Qu.:36.00
## Max. :17.000 Max. :199.0 Max. :122.00 Max. :99.00
## Insulin BMI DiabetesPedigreeFunction Age
## Min. : 14.00 Min. :18.20 Min. :0.0780 Min. :21.00
## 1st Qu.: 73.75 1st Qu.:27.50 1st Qu.:0.2437 1st Qu.:24.00
## Median :120.00 Median :32.30 Median :0.3725 Median :29.00
## Mean :148.57 Mean :32.47 Mean :0.4719 Mean :33.24
## 3rd Qu.:182.00 3rd Qu.:36.60 3rd Qu.:0.6262 3rd Qu.:41.00
## Max. :846.00 Max. :67.10 Max. :2.4200 Max. :81.00
## Outcome
## Min. :0.000
## 1st Qu.:0.000
## Median :0.000
## Mean :0.349
## 3rd Qu.:1.000
## Max. :1.000
En este resumen de la base de datos podemos identificar lo siguiente,
varibles como Pregnancies
tiene un maximo de 17, lo que
puede ser un outlier dentro de esta variable. La variable
Glucose
que tiene un valor maximo de 199, que es un nivel
alto para esa medida. LA variable Insulin
tiene un valor de
846 que muy por encima del promedio.
Resumen visual con histograma para identificar outliers.
df_long <- pivot_longer(df_pmm,
cols = c(Pregnancies, Glucose, BloodPressure, SkinThickness, Insulin, BMI, DiabetesPedigreeFunction, Age),
names_to = "Variable",
values_to = "Valor")
ggplot(df_long, aes(x = Valor)) +
geom_histogram(bins = 30, fill = "#FBD000", color = "red") +
facet_wrap(~ Variable, scales = "free", nrow = 2, ncol = 4) +
labs(title = "Histogramas de las variables",
x = "Valores",
y = "Frecuencia") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5))
En los histogramas podemos identificar variables como
age
que tienen valores distantes como 81, otra es
BMI
que tiene un valor cercano a 70 que esta distante de
los otros, otra variable que vemos en el histograma es
Insulin
que habiamos detectado con el resumen anterior con
un valor en 846.
Realizamos un boxplot multiple para saber que variables tienen datos atipicos.
df_analisis <- df_pmm[, c('Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'DiabetesPedigreeFunction', 'Age')]
df_melted <- melt(df_analisis)
## No id variables; using all as measure variables
ggplot(df_melted, aes(x = "", y = value)) +
geom_boxplot(fill = "#FBD000", color = "red") +
theme_minimal() +
labs(y = "Valor", x = "") +
facet_wrap(~variable, scales = "free_y", ncol = 4) +
theme(panel.grid.major = element_line(color = "gray80", linetype = "dotted"),
panel.grid.minor = element_blank())
Del boxplot podemos identificar que la variable
Pregnancies
tiene 3 outliers, Bloodpressure
tiene aproximadamente 5, SkinThikenss
tiene 3 outliers y
aparte de esas vemos 4 variables mas como
Ìnsulin, BMI, Diabetes, Age
tienen outliers.
Con estemetodo vamos a calcular los valores que se encuentren por debajo del 2.5% y por encima del 97.5% de los datos detectandolos como outliers.
variables_predictores <- setdiff(names(df_pmm), "Outcome")
percentil_bajo <- 0.025
percentil_alto <- 0.975
cat("Valores atípicos detectados por el método de percentiles (", percentil_bajo * 100, "% y ", percentil_alto * 100, "%):\n\n")
## Valores atípicos detectados por el método de percentiles ( 2.5 % y 97.5 %):
for (col in variables_predictores) {
lower_bound <- quantile(df_pmm[[col]], percentil_bajo, na.rm = TRUE)
upper_bound <- quantile(df_pmm[[col]], percentil_alto, na.rm = TRUE)
outliers_low <- df_pmm[[col]][df_pmm[[col]] < lower_bound]
outliers_high <- df_pmm[[col]][df_pmm[[col]] > upper_bound]
total_outliers <- length(outliers_low) + length(outliers_high)
cat("---", col, "---\n")
cat("Límite inferior (", percentil_bajo * 100, "%):", lower_bound, "\n")
cat("Límite superior (", percentil_alto * 100, "%):", upper_bound, "\n")
if (length(outliers_low) > 0) {
cat("Valores por debajo del límite inferior:\n")
print(outliers_low)
}
if (length(outliers_high) > 0) {
cat("Valores por encima del límite superior:\n")
print(outliers_high)
}
cat("Total de outliers encontrados:", total_outliers, "\n")
cat("\n")
}
## --- Pregnancies ---
## Límite inferior ( 2.5 %): 0
## Límite superior ( 97.5 %): 12
## Valores por encima del límite superior:
## [1] 13 13 13 15 17 13 14 13 13 14 13 13 13 13
## Total de outliers encontrados: 14
##
## --- Glucose ---
## Límite inferior ( 2.5 %): 73.175
## Límite superior ( 97.5 %): 189
## Valores por debajo del límite inferior:
## [1] 71 73 44 62 71 57 71 73 71 61 72 71 68 57 73 67 68 68 56 65
## Valores por encima del límite superior:
## [1] 197 196 194 196 197 193 191 194 196 193 197 194 195 198 198 197 199 195 190
## Total de outliers encontrados: 39
##
## --- BloodPressure ---
## Límite inferior ( 2.5 %): 50
## Límite superior ( 97.5 %): 97.65
## Valores por debajo del límite inferior:
## [1] 40 30 48 44 48 48 30 48 46 48 44 44 24 38 44 46 44
## Valores por encima del límite superior:
## [1] 110 108 122 110 98 104 98 100 108 102 100 100 104 98 110 106 106 106 100
## [20] 114
## Total de outliers encontrados: 37
##
## --- SkinThickness ---
## Límite inferior ( 2.5 %): 11
## Límite superior ( 97.5 %): 48
## Valores por debajo del límite inferior:
## [1] 10 10 7 7 10 10 8 8 10 8 7 10 7
## Valores por encima del límite superior:
## [1] 49 60 54 51 56 50 54 50 52 60 49 49 63 52 49 99 50 60 49
## Total de outliers encontrados: 32
##
## --- Insulin ---
## Límite inferior ( 2.5 %): 25.7
## Límite superior ( 97.5 %): 480
## Valores por debajo del límite inferior:
## [1] 23 23 15 18 23 23 15 14 16 23 18 25 25 25 15 18 23 23 22 16
## Valores por encima del límite superior:
## [1] 543 545 846 495 485 495 744 680 680 545 540 579 540 543 600 540 846 510 510
## Total de outliers encontrados: 39
##
## --- BMI ---
## Límite inferior ( 2.5 %): 21
## Límite superior ( 97.5 %): 46.665
## Valores por debajo del límite inferior:
## [1] 19.9 19.4 19.6 19.1 20.4 20.4 18.4 20.8 19.3 20.0 18.2 18.2 19.6 20.8 19.6
## [16] 18.2 19.5 20.1 19.5
## Valores por encima del límite superior:
## [1] 46.8 46.8 48.8 46.7 49.7 53.2 55.0 47.9 50.0 67.1 52.3 52.3 52.9 47.9 48.3
## [16] 59.4 46.8 57.3 49.6 49.3
## Total de outliers encontrados: 39
##
## --- DiabetesPedigreeFunction ---
## Límite inferior ( 2.5 %): 0.123525
## Límite superior ( 97.5 %): 1.31345
## Valores por debajo del límite inferior:
## [1] 0.102 0.088 0.096 0.085 0.084 0.101 0.089 0.092 0.078 0.123 0.122 0.108
## [13] 0.107 0.121 0.085 0.088 0.100 0.115 0.118 0.121
## Valores por encima del límite superior:
## [1] 2.288 1.441 1.390 1.893 1.781 1.400 1.321 2.329 1.318 1.353 1.391 1.476
## [13] 2.137 1.731 1.600 2.420 1.699 1.698 1.461 1.394
## Total de outliers encontrados: 40
##
## --- Age ---
## Límite inferior ( 2.5 %): 21
## Límite superior ( 97.5 %): 63
## Valores por encima del límite superior:
## [1] 69 65 66 65 65 67 72 81 67 66 64 67 66 70 68 69 66
## Total de outliers encontrados: 17
Vemos que con este metodo para la variable Pregnancies
detecta 14 otliers a diferencia del metodo del boxplot que solo
identifica 3, para la variable Glucose
detecta 39 outliers,
para la variable BloodPressure
detecta 37 outliers , para
la variable SkinThickness
detecta 32 outliers.
Insulin
detecta 39, BMI
detecta 39,
DiabetesPedigreeFunction
detecta 40 outliers,
Age
detecta 17 outliers.
Este Metodo consiste en considerar como valores atípicos los valores fuera del intervalo formado por la mediana, más o menos 3 desviaciones absolutas de la mediana:
variables_predictores <- setdiff(names(df_pmm), "Outcome")
cat("Valores atípicos detectados por el método de Hampel manual:\n\n")
## Valores atípicos detectados por el método de Hampel manual:
for (col in variables_predictores) {
mediana <- median(df_pmm[[col]])
mad_valor <- mad(df_pmm[[col]], constant = 1)
lower_bound <- mediana - (3 * mad_valor)
upper_bound <- mediana + (3 * mad_valor)
outliers <- df_pmm[[col]][df_pmm[[col]] < lower_bound | df_pmm[[col]] > upper_bound]
total_outliers <- length(outliers)
cat("---", col, "---\n")
cat("Límite inferior:", lower_bound, "\n")
cat("Límite superior:", upper_bound, "\n")
if (total_outliers > 0) {
cat("Valores atípicos:\n")
print(outliers)
cat("Total de outliers encontrados:", total_outliers, "\n")
}
cat("\n")
}
## --- Pregnancies ---
## Límite inferior: -3
## Límite superior: 9
## Valores atípicos:
## [1] 10 10 10 11 10 13 10 11 13 13 15 10 17 11 12 10 12 11 10 13 10 14 10 13 10
## [26] 12 13 12 12 12 14 10 10 10 12 13 10 11 11 10 12 11 11 10 13 11 11 10 10 10
## [51] 13 10 10 10 11 13 12 10
## Total de outliers encontrados: 58
##
## --- Glucose ---
## Límite inferior: 57
## Límite superior: 177
## Valores atípicos:
## [1] 183 197 189 196 180 180 187 44 188 179 194 181 196 184 179 197 181 179 184
## [20] 193 191 182 194 179 180 178 196 189 193 197 184 181 189 180 194 195 198 180
## [39] 186 187 189 198 197 188 183 181 183 179 199 195 56 187 187 181 190
## Total de outliers encontrados: 55
##
## --- BloodPressure ---
## Límite inferior: 48
## Límite superior: 96
## Valores atípicos:
## [1] 40 30 110 44 108 122 30 110 98 104 98 46 100 108 102 100 100 104 98
## [20] 110 44 44 24 38 106 106 106 100 114 44 46 44
## Total de outliers encontrados: 32
##
## --- SkinThickness ---
## Límite inferior: 8
## Límite superior: 50
## Valores atípicos:
## [1] 60 54 51 56 7 54 7 52 60 63 7 52 99 60 7
## Total de outliers encontrados: 15
##
## --- Insulin ---
## Límite inferior: -42
## Límite superior: 282
## Valores atípicos:
## [1] 543 545 846 342 480 300 342 304 415 440 495 325 325 284 485 285 370 392 495
## [20] 285 318 300 478 744 330 370 680 285 680 402 375 293 480 545 360 330 480 325
## [39] 293 465 325 285 321 415 540 579 310 474 540 370 285 328 480 375 321 543 326
## [58] 330 370 600 321 293 321 440 540 846 318 510 321 480 335 387 291 392 480 480
## [77] 510 318
## Total de outliers encontrados: 78
##
## --- BMI ---
## Límite inferior: 18.5
## Límite superior: 46.1
## Valores atípicos:
## [1] 46.8 46.8 48.8 46.7 49.7 53.2 55.0 47.9 50.0 67.1 52.3 46.2 18.4 52.3 52.9
## [16] 47.9 48.3 18.2 18.2 59.4 46.5 18.2 46.2 46.8 57.3 49.6 49.3 46.3
## Total de outliers encontrados: 28
##
## --- DiabetesPedigreeFunction ---
## Límite inferior: -0.13
## Límite superior: 0.875
## Valores atípicos:
## [1] 2.288 1.441 0.966 1.390 1.893 0.962 1.781 1.222 0.930 1.114 1.400 1.189
## [13] 0.956 1.321 0.905 1.224 1.072 2.329 1.318 1.213 0.926 1.353 0.997 0.933
## [25] 1.101 1.136 0.881 1.224 1.391 1.127 1.476 0.932 0.893 0.962 2.137 1.731
## [37] 1.021 0.947 1.268 0.949 1.600 0.944 1.191 1.076 1.095 1.138 0.955 2.420
## [49] 1.001 1.022 1.159 1.144 0.968 0.917 1.251 0.968 1.034 0.892 1.154 0.925
## [61] 1.699 1.258 0.878 1.282 1.698 1.461 1.162 1.292 1.394 0.880 0.886 0.904
## [73] 0.905 0.970 1.174 1.096 1.182 1.057
## Total de outliers encontrados: 78
##
## --- Age ---
## Límite inferior: 8
## Límite superior: 50
## Valores atípicos:
## [1] 53 54 57 59 51 51 57 60 56 54 58 54 60 61 69 62 55 65 60 55 57 52 60 66 61
## [26] 51 51 63 52 57 52 51 65 58 59 57 63 65 67 58 58 55 72 62 51 81 59 63 58 67
## [51] 66 55 64 58 53 51 60 67 56 53 66 58 54 62 62 52 52 54 51 54 70 68 53 69 52
## [76] 56 52 53 52 66 63
## Total de outliers encontrados: 81
Vemos que con este metodo se estan detectando mas outliers en unas
variables y en otras encuentre menos que el metodo de los percentiles,
para la variable Pregnancies
detecta 58 outliers a
diferencia del metodo anterior que detecto solamente 14 otliers, para la
variable Glucose
detecta 55 outliers a diferencia del
metodo anterior que encontro 39 outliers, para la variable
BloodPressure
detecta 32 outliers a diferencia de 37
outliers que detecot el anterior, en este caso el metodo de los
percentiles detecto 5 outliers mas que este metodo del filtro de Hampel,
para la variable SkinThickness
detecta 15 a diferencia del
metodo anterior que encontro 32 outliers. Insulin
detecta 78
a diferencia del metodo anterior que encontro 39, BMI
detecta 28 con este metodo y con el anterior detecto 39,
DiabetesPedigreeFunction
detecta 78 outliers a diferencia
de los 40 outliers que encontro en el anterior, Age
detecta
81 outliers a diferencia de 17 outliers que encontro en el metodo
anterior.
La prueba de Grubbs permite detectar si el valor más alto o más bajo de un conjunto de datos es un valor atípico.
H_0: El valor más alto/bajo no es un valor atípico
H_1: El valor más alto/bajo es un valor atípico
Realizamos un resumen de nuestros datos debido a que Grubbs por defecto toma como valor objetivo el maximo de esa variable
## Pregnancies Glucose BloodPressure SkinThickness
## Min. : 0.000 Min. : 44.0 Min. : 24.00 Min. : 7.00
## 1st Qu.: 1.000 1st Qu.: 99.0 1st Qu.: 64.00 1st Qu.:21.00
## Median : 3.000 Median :117.0 Median : 72.00 Median :29.00
## Mean : 3.845 Mean :121.7 Mean : 72.42 Mean :28.82
## 3rd Qu.: 6.000 3rd Qu.:141.0 3rd Qu.: 80.00 3rd Qu.:36.00
## Max. :17.000 Max. :199.0 Max. :122.00 Max. :99.00
## Insulin BMI DiabetesPedigreeFunction Age
## Min. : 14.00 Min. :18.20 Min. :0.0780 Min. :21.00
## 1st Qu.: 73.75 1st Qu.:27.50 1st Qu.:0.2437 1st Qu.:24.00
## Median :120.00 Median :32.30 Median :0.3725 Median :29.00
## Mean :148.57 Mean :32.47 Mean :0.4719 Mean :33.24
## 3rd Qu.:182.00 3rd Qu.:36.60 3rd Qu.:0.6262 3rd Qu.:41.00
## Max. :846.00 Max. :67.10 Max. :2.4200 Max. :81.00
## Outcome
## Min. :0.000
## 1st Qu.:0.000
## Median :0.000
## Mean :0.349
## 3rd Qu.:1.000
## Max. :1.000
Para la primera prueba usaremos la variable
Pregnancies
.
##
## Grubbs test for one outlier
##
## data: df_pmm$Pregnancies
## G = 3.9040, U = 0.9801, p-value = 0.03367
## alternative hypothesis: highest value 17 is an outlier
Como el P-valor es menor que (0.05) tenemos evidencia estadisticamente significativa para rechazar H_0, por lo que 17 es un outliers.
Para la segunda prueba usaremos la variable Glucose
.
##
## Grubbs test for one outlier
##
## data: df_pmm$Glucose
## G = 2.53239, U = 0.99163, p-value = 1
## alternative hypothesis: lowest value 44 is an outlier
Como el p-valor es mayor que (0.05) no tenemos evidencia estadisticamente significativa para rechazar H_0, por lo que 199 no es un outliers.
Para la tercera prueba usaremos la variable
BloodPressure
.
##
## Grubbs test for one outlier
##
## data: df_pmm$BloodPressure
## G = 4.01506, U = 0.97895, p-value = 0.02096
## alternative hypothesis: highest value 122 is an outlier
Como el P-valor es menor que (0.05) tenemos evidencia estadisticamente significativa para rechazar H_0, por lo que 122 es un outliers.
Para la cuarta prueba usaremos la variable
BloodPressure
.
##
## Grubbs test for one outlier
##
## data: df_pmm$SkinThickness
## G = 6.76548, U = 0.94025, p-value = 2.505e-09
## alternative hypothesis: highest value 99 is an outlier
Como el P-valor es menor que (0.05) tenemos evidencia estadisticamente significativa para rechazar H_0, por lo que 99 es un outliers.
Para la quinta prueba usaremos la variable Insulin
.
##
## Grubbs test for one outlier
##
## data: df_pmm$Insulin
## G = 6.0952, U = 0.9515, p-value = 2.637e-07
## alternative hypothesis: highest value 846 is an outlier
Como el P-valor es menor que (0.05) tenemos evidencia estadisticamente significativa para rechazar H_0, por lo que 9846 es un outliers.
Para la sexta prueba usaremos la variable BMI
.
##
## Grubbs test for one outlier
##
## data: df_pmm$BMI
## G = 5.01023, U = 0.96723, p-value = 0.0001693
## alternative hypothesis: highest value 67.1 is an outlier
Como el P-valor es menor que (0.05) tenemos evidencia estadisticamente significativa para rechazar H_0, por lo que 67 es un outliers.
Para la septima prueba usaremos la variable
DiabetesPedigreeFunction
.
##
## Grubbs test for one outlier
##
## data: df_pmm$DiabetesPedigreeFunction
## G = 5.87973, U = 0.95487, p-value = 1.056e-06
## alternative hypothesis: highest value 2.42 is an outlier
Como el P-valor es menor que (0.05) tenemos evidencia estadisticamente significativa para rechazar H_0, por lo que 2.42 es un outliers.
Para la octava prueba usaremos la variable Age
.
##
## Grubbs test for one outlier
##
## data: df_pmm$Age
## G = 4.06107, U = 0.97847, p-value = 0.01716
## alternative hypothesis: highest value 81 is an outlier
Como el P-valor es menor que (0.05) tenemos evidencia estadisticamente significativa para rechazar H_0, por lo que 81 es un outliers.
Para realizar esta prueba, es necesario que el n<25 y en nuestro caso el dataset tiene 768 observaciones
Se utiliza para detectar varios valores atípicos a la vez (a diferencia de la prueba de Grubbs y Dixon, que debe realizarse de forma iterativa para detectar múltiples valores atípicos), y está diseñado para evitar el problema del enmascaramiento, en el que un valor atípico cercano a otro atípico puede pasar desapercibido.
Para la primera prueba usaremos la variable Pregnancies
.
El parametro k lo estamos tomando dependiendo el numero de outliers se
vean en el boxplot de la variable respectiva.
## i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
## 1 0 3.845052 3.369578 17 160 3.904034 3.974092 FALSE
## 2 1 3.827901 3.338063 15 89 3.346880 3.973762 FALSE
## 3 2 3.813316 3.315699 14 299 3.072258 3.973432 FALSE
Con este metodo vemos que de los tres valores que esta encontrando, ninguno de estos es un outliers.
## i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
## 1 0 121.6784 30.67391 44 63 2.532393 3.974092 FALSE
Con este metodo vemos que el valor que esta encontrando, no es un outliers.
## i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
## 1 0 72.41536 12.34967 122 107 4.015058 3.974092 TRUE
## 2 1 72.35072 12.22700 24 598 3.954422 3.973762 FALSE
## 3 2 72.41384 12.10930 30 19 3.502585 3.973432 FALSE
## 4 3 72.46928 12.01954 30 126 3.533354 3.973102 FALSE
## 5 4 72.52487 11.92861 114 692 3.476947 3.972771 FALSE
Con este metodo vemos que de los cinco valores que esta encontrando, vemos que el 122 es un outliers.
## i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
## 1 0 28.82161 10.373002 99 580 6.765485 3.974092 TRUE
## 2 1 28.73012 10.064877 63 446 3.404898 3.973762 FALSE
## 3 2 28.68538 9.994847 60 58 3.133077 3.973432 FALSE
Con este metodo vemos que de los tres valores que esta encontrando, vemos que el 99 es un outliers.
## i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
## 1 0 148.5651 114.42331 846 14 6.095217 3.974092 TRUE
## 2 1 147.6558 111.68685 846 662 6.252699 3.973762 TRUE
## 3 2 146.7441 108.86657 744 229 5.486128 3.973432 TRUE
## 4 3 145.9634 106.77045 680 238 5.001727 3.973102 TRUE
## 5 4 145.2644 105.07425 680 248 5.089121 3.972771 TRUE
## 6 5 144.5636 103.34091 600 585 4.407126 3.972440 TRUE
## 7 6 143.9659 102.08062 579 410 4.261672 3.972108 TRUE
## 8 7 143.3942 100.91986 545 12 3.979452 3.971776 TRUE
## 9 8 142.8658 99.92726 545 287 4.024269 3.971443 TRUE
## 10 9 142.3360 98.91921 543 9 4.050417 3.971110 TRUE
## 11 10 141.8074 97.90604 543 503 4.097731 3.970776 TRUE
## 12 11 141.2774 96.87666 540 405 4.115776 3.970442 TRUE
## 13 12 140.7500 95.84712 540 456 4.165488 3.970107 TRUE
## 14 13 140.2212 94.80067 540 656 4.217046 3.969772 TRUE
## 15 14 139.6910 93.73672 510 676 3.950523 3.969437 FALSE
Con este metodo vemos que de los quince valores que esta encontrando, todos a exepción de el 510 son outliers.
## i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
## 1 0 32.46745 6.912365 67.1 178 5.010232 3.974092 TRUE
## 2 1 32.42229 6.802596 59.4 446 3.965796 3.973762 FALSE
## 3 2 32.38708 6.736705 57.3 674 3.698088 3.973432 FALSE
## 4 3 32.35451 6.680506 55.0 126 3.389787 3.973102 FALSE
## 5 4 32.32487 6.634355 53.2 121 3.146520 3.972771 FALSE
## 6 5 32.29751 6.595438 52.9 304 3.123749 3.972440 FALSE
Con este metodo vemos que de los seis valores que esta encontrando, vemos que el 67 es un outliers.
## i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
## 1 0 0.4718763 0.3313286 2.420 446 5.879733 3.974092 TRUE
## 2 1 0.4693364 0.3239768 2.329 229 5.740114 3.973762 TRUE
## 3 2 0.4669086 0.3171301 2.288 5 5.742410 3.973432 TRUE
Con este metodo vemos que de los tres valores que esta encontrando, todos son outliers.
## i Mean.i SD.i Value Obs.Num R.i+1 lambda.i+1 Outlier
## 1 0 33.24089 11.76023 81 460 4.061069 3.974092 TRUE
## 2 1 33.17862 11.64053 72 454 3.335018 3.973762 FALSE
## 3 2 33.12794 11.56315 70 667 3.188755 3.973432 FALSE
## 4 3 33.07974 11.49346 69 124 3.125278 3.973102 FALSE
## 5 4 33.03272 11.42714 69 685 3.147531 3.972771 FALSE
## 6 5 32.98558 11.36006 68 675 3.082239 3.972440 FALSE
## 7 6 32.93963 11.29634 67 364 3.015167 3.972108 FALSE
## 8 7 32.89488 11.23596 67 490 3.035354 3.971776 FALSE
## 9 8 32.85000 11.17491 67 538 3.055953 3.971443 FALSE
## 10 9 32.80501 11.11318 66 222 2.986993 3.971110 FALSE
## 11 10 32.76121 11.05479 66 496 3.006731 3.970776 FALSE
## 12 11 32.71731 10.99576 66 553 3.026866 3.970442 FALSE
## 13 12 32.67328 10.93608 66 760 3.047411 3.970107 FALSE
## 14 13 32.62914 10.87572 65 149 2.976433 3.969772 FALSE
## 15 14 32.58621 10.81873 65 295 2.996080 3.969437 FALSE
## 16 15 32.54316 10.76112 65 363 3.016122 3.969101 FALSE
## 17 16 32.50000 10.70286 64 510 2.943138 3.968764 FALSE
## 18 17 32.45806 10.64797 63 264 2.868335 3.968427 FALSE
Con este metodo vemos que de los 18 valores que esta encontrando, solo el 21 es un outliers.
Se aplicó la técnica de capping basada en percentiles para atenuar el efecto de valores atípicos extremos, reemplazándolos por los límites de los cuartiles y preservando así la estructura general de los datos sin eliminarlos.
capping_iqr <- function(x) {
Q1 <- quantile(x, 0.25, na.rm = TRUE)
Q3 <- quantile(x, 0.75, na.rm = TRUE)
IQR_val <- Q3 - Q1
lower <- Q1 - 1.5 * IQR_val
upper <- Q3 + 1.5 * IQR_val
x[x < lower] <- lower
x[x > upper] <- upper
return(x)
}
df_capped <- df_pmm
variables_predictores <- setdiff(names(df_capped), "Outcome")
df_melted <- melt(df_capped[, variables_predictores])
## No id variables; using all as measure variables
ggplot(df_melted, aes(x = "", y = value)) +
geom_boxplot(fill = "#FBD000", color = "red") +
theme_minimal() +
labs(title = "Boxplot inicial", x = "", y = "Valor") +
facet_wrap(~variable, scales = "free_y")
for (col in variables_predictores) {
df_capped[[col]] <- capping_iqr(df_capped[[col]])
}
df_melted_final <- melt(df_capped[, variables_predictores])
## No id variables; using all as measure variables
ggplot(df_melted_final, aes(x = "", y = value)) +
geom_boxplot(fill = "#FBD000", color = "red") +
theme_minimal() +
labs(title = "Boxplot después de capping por IQR", x = "", y = "Valor") +
facet_wrap(~variable, scales = "free_y")
Tras aplicar el capping, los boxplots muestran una distribución más uniforme y sin valores atípicos extremos, lo que facilita un análisis más estable y representativo de las variables.
Una vez imputados los valores faltantes y tratados los datos atípicos, procedemos a realizar el análisis exploratorio de datos para identificar patrones, relaciones y tendencias relevantes en el conjunto.
Se presenta un resumen detallado de todas las variables del dataset, incluyendo el tipo de dato (entero, punto flotante o carácter).
## Rows: 768
## Columns: 9
## $ Pregnancies <dbl> 6, 1, 8, 1, 0, 5, 3, 10, 2, 8, 4, 10, 10, 1, …
## $ Glucose <dbl> 148, 85, 183, 89, 137, 116, 78, 115, 197, 125…
## $ BloodPressure <dbl> 72, 66, 64, 66, 40, 74, 50, 72, 70, 96, 92, 7…
## $ SkinThickness <dbl> 35, 29, 20, 23, 35, 24, 32, 37, 45, 37, 32, 4…
## $ Insulin <dbl> 83.000, 55.000, 175.000, 94.000, 168.000, 175…
## $ BMI <dbl> 33.6, 26.6, 23.3, 28.1, 43.1, 25.6, 31.0, 35.…
## $ DiabetesPedigreeFunction <dbl> 0.627, 0.351, 0.672, 0.167, 1.200, 0.201, 0.2…
## $ Age <dbl> 50, 31, 32, 21, 33, 30, 26, 29, 53, 54, 30, 3…
## $ Outcome <int> 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, …
Se calcula el número de valores faltantes para cada variable del DataFrame.
## Pregnancies Glucose BloodPressure
## 0 0 0
## SkinThickness Insulin BMI
## 0 0 0
## DiabetesPedigreeFunction Age Outcome
## 0 0 0
Vemos que tenemos el 100% de las observaciones y ningun dato
faltantes.
Se calcula el número de valores únicos para cada variable del DataFrame.
## Pregnancies Glucose BloodPressure
## 15 135 38
## SkinThickness Insulin BMI
## 48 163 241
## DiabetesPedigreeFunction Age Outcome
## 490 47 2
En esta sección analizaremos cada variable por separado para entender su distribución y características principales.
Variable Pregnancies (Número de embarazos)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000 1.000 3.000 3.837 6.000 13.500
hist(df_capped$Pregnancies, main = "Distribución del número de embarazos",
xlab = "Número de embarazos", ylab = "Frecuencia",
col = "#FBD000", border = "red")
## Kurtosis: -0.07085283
## Skewness: 0.8539617
Interpretación
para nuestra variable tenemos un minimo de 0 y un maximo de 13 embarazos, vemos que el el 50% de los datos se encuentra por debajo de 3. Con un valor de skewness de 0.85, la distribución del número de embarazos presenta un sesgo positivo, lo que indica que la mayoría de los pacientes han tenido pocos embarazos y existe una cola larga de pacientes con un número mayor. El kurtosis de -0.07, un valor muy cercano a cero, sugiere que el grosor de las colas es similar al de una distribución normal.
Variable Glucose (Concentración de glucosa)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 44.0 99.0 117.0 121.7 141.0 199.0
hist(df_capped$Glucose, main = "Histograma de niveles de glucosa",
xlab = "Glucosa (mg/dL)", col = "#FBD000", border = "red")
## Kurtosis: -0.2789814
## Skewness: 0.5339174
Interpretación
a variable Glucosa presenta un sesgo positivo de 0.53, lo que indica que la distribución de los datos se inclina hacia los valores bajos, con una cola de valores más altos que se extiende a la derecha. El valor de kurtosis de -0.28 sugiere que la distribución es más plana que una normal, con colas más ligeras. El resumen estadístico complementa esta información al mostrar que la media (121.7) es mayor que la mediana (117.0), lo que es una característica de las distribuciones con sesgo positivo. La mayoría de los pacientes tienen niveles de glucosa entre 99.0 y 141.0 mg/dL.
Variable BloodPressre
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 40.00 64.00 72.00 72.39 80.00 104.00
hist(df_capped$BloodPressure, main = "Histograma de BloodPressure",
xlab = "BloodPressure (mm Hg)", col = "#FBD000", border = "red")
## Kurtosis: 0.06444744
## Skewness: 0.0998705
Interpretación
La distribución de la variable BloodPressure es casi normal y simétrica, como lo indica su valor de skewness (sesgo) de 0.0998, que está muy cerca de cero. Esto se confirma visualmente en el histograma, que muestra una forma de campana centrada en el rango de 70-80 mm Hg. El valor de kurtosis (curtosis) de 0.064, también muy cercano a cero, sugiere que el pico de la distribución y el grosor de sus colas son similares a los de una distribución normal. Las estadísticas del summary respaldan esta simetría, ya que la media (72.39) y la mediana (72.00) son casi idénticas. La mayor parte de los datos se encuentra en un rango estrecho, del primer cuartil de 64.00 al tercer cuartil de 80.00, con un mínimo de 40.00 y un máximo de 104.00.
Variable SkinThickness
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 7.00 21.00 29.00 28.76 36.00 58.50
hist(df_capped$SkinThickness, main = "Histograma de SkinThickness",
xlab = "SkinThickness (mm)", col = "#FBD000", border = "red")
## Kurtosis: -0.3638711
## Skewness: 0.2147364
Interpretación
La distribución de la variable SkinThickness es ligeramente sesgada a la derecha, como lo indica el valor de skewness de 0.21. Aunque el sesgo es leve, se observa en el histograma una cola más larga hacia los valores altos. El valor de kurtosis es -0.36, lo que sugiere que la distribución es más plana que una distribución normal, con colas menos gruesas. Las estadísticas del summary muestran que la media (28.76) es ligeramente mayor que la mediana (29.00), lo cual es inusual para una distribución con sesgo positivo. Sin embargo, la mayor parte de los datos se concentra entre los 21.00 mm (primer cuartil) y 36.00 mm (tercer cuartil), con un rango total desde un mínimo de 7.00 mm hasta un máximo de 58.50 mm.
Variable Insulin
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 14.00 73.75 120.00 139.76 182.00 344.38
hist(df_capped$Insulin, main = "Histograma de Insulin",
xlab = "Insulin (µU/mL)", col = "#FBD000", border = "red")
## Kurtosis: 0.1450276
## Skewness: 0.9466988
Interpretación
La distribución de la variable Insulin presenta un sesgo positivo de 0.94, lo cual es considerable y se observa en el histograma. La mayoría de los valores de insulina se agrupan en el extremo inferior, y hay una cola larga de valores altos que se extiende hacia la derecha. La kurtosis de 0.14 es ligeramente positiva, sugiriendo que la distribución es un poco más puntiaguda que una distribución normal, con colas moderadamente más gruesas. Las estadísticas del summary confirman el sesgo, ya que la media (139.76) es notablemente mayor que la mediana (120.00). El rango intercuartílico, entre 73.75 y 182.00, contiene la mayoría de los datos, mientras que los valores de insulina alcanzan un máximo de 344.38.
Variable BMI
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 18.20 27.50 32.30 32.41 36.60 50.25
## Kurtosis: -0.2328969
## Skewness: 0.3495582
Interpretación
La distribución de la variable BMI muestra un sesgo positivo de 0.35, lo cual indica que la mayoría de los valores se concentran en el rango bajo a medio, con una cola más larga de pacientes con un IMC más alto. El histograma confirma esta ligera inclinación hacia la derecha. El valor de kurtosis de -0.23 sugiere que la distribución es más plana que una normal, con colas menos gruesas. Las estadísticas del summary muestran que la media (32.41) es ligeramente mayor que la mediana (32.30), lo cual es coherente con el sesgo positivo. La mayor parte de los pacientes tiene un IMC entre 27.50 y 36.60, con valores que oscilan entre un mínimo de 18.20 y un máximo de 50.25.
Variable DiabetesPedigreeFunction
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.0780 0.2437 0.3725 0.4589 0.6262 1.2000
hist(df_capped$DiabetesPedigreeFunction, main = "Histograma de DiabetesPedigreeFunction",
xlab = "Diabetes Pedigree Function", col = "#FBD000", border = "red")
## Kurtosis: 0.2974468
## Skewness: 1.024428
Interpretación
La distribución de la variable DiabetesPedigreeFunction muestra un sesgo positivo significativo con un valor de 1.02. Esto es claramente visible en el histograma, donde la mayoría de los valores se agrupan en el extremo inferior, y hay una cola larga que se extiende a la derecha, lo que indica que una pequeña cantidad de pacientes tiene una predisposición genética a la diabetes muy alta. El valor de kurtosis es 0.297, ligeramente positivo, lo que sugiere que la distribución es un poco más puntiaguda que una distribución normal, con colas moderadamente más gruesas. Las estadísticas del summary confirman el sesgo: la media (0.4589) es notablemente más alta que la mediana (0.3725). Los datos se concentran en gran medida entre el primer cuartil (0.2437) y el tercer cuartil (0.6262), con valores que van desde un mínimo de 0.0780 hasta un máximo de 1.2000.
Variable Age
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 21.0 24.0 29.0 33.2 41.0 66.5
hist(df_capped$Age, main = "Histograma de Age",
xlab = "Edad (años)", col = "#FBD000", border = "red")
## Kurtosis: 0.3309699
## Skewness: 1.06717
Interpretación
La variable Age tiene un sesgo positivo considerable de 1.06, lo cual se visualiza en el histograma. La mayoría de los pacientes son jóvenes, con una alta concentración en el rango de los 20-30 años, y la frecuencia disminuye a medida que aumenta la edad, formando una larga cola hacia la derecha. El valor de kurtosis de 0.33 es ligeramente positivo, lo que indica que la distribución es un poco más puntiaguda con colas más gruesas que una distribución normal. El resumen estadístico confirma el sesgo, ya que la media (33.2) es superior a la mediana (29.0). El rango intercuartílico se encuentra entre los 24.0 y 41.0 años, con un mínimo de 21.0 y un máximo de 66.5.
Variable Outcome (Variable objetivo)
##
## 0 1
## 65.10417 34.89583
barplot(table(df_capped$Outcome), main = "Proporción de casos de diabetes",
names.arg = c("No diabetes", "Diabetes"),
col = c("#FBD000", "red"), ylab = "Frecuencia")
Interpretación
La salida prop.table muestra que el 65.10% de los pacientes en el conjunto de datos no tienen diabetes (representado por el valor 0), mientras que el 34.90% de los pacientes sí tienen diabetes (representado por el valor 1). El gráfico de barras confirma visualmente esta distribución, mostrando una barra significativamente más alta para el grupo “No diabetes”.
El análisis bivariado sirve para explorar la relación entre dos variables a la vez, permitiendo identificar si existe una asociación, su dirección (positiva o negativa) y su fuerza.
Pregnancies vs Outcome
ggplot(df_capped, aes(x = factor(Outcome, labels = c("No diabetes", "Diabetes")),
y = Pregnancies,
fill = factor(Outcome))) +
geom_boxplot(outlier.shape = 21, outlier.fill = "white", outlier.color = "black", width = 0.5) +
scale_fill_manual(values = c("#FBD000", "red")) +
labs(
title = "Número de embarazos vs Diabetes",
x = "",
y = "Número de embarazos"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "none",
axis.text = element_text(color = "black"),
panel.grid.major = element_line(color = "gray80"),
panel.grid.minor = element_line(color = "gray90")
)
Interpretación
El boxplot muestra una clara asociación entre el número de embarazos y el diagnóstico de diabetes. La mediana del número de embarazos en las pacientes con diabetes (aproximadamente 4) es más alta que la mediana de aquellas sin la enfermedad (aproximadamente 2). Esto sugiere que las pacientes con diabetes tienden a haber tenido un mayor número de embarazos y que esta variable podría ser un factor de riesgo.
Glucose vs Outcome
ggplot(df_capped, aes(x = factor(Outcome, labels = c("No diabetes", "Diabetes")),
y = Glucose,
fill = factor(Outcome))) +
geom_boxplot(outlier.shape = 21, outlier.fill = "white", outlier.color = "black", width = 0.5) +
scale_fill_manual(values = c("#FBD000", "red"),
name = "Diabetes",
labels = c("No", "Sí")) +
labs(
title = "Niveles de glucosa por condición de diabetes",
x = "",
y = "Glucosa"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
axis.text = element_text(color = "black"),
panel.grid.major = element_line(color = "gray80"),
panel.grid.minor = element_line(color = "gray90"),
legend.position = "top"
)
Interpretación
El boxplot de los niveles de glucosa por condición de diabetes muestra una clara y fuerte asociación entre la glucosa y el diagnóstico de diabetes. La mediana de glucosa para el grupo con diabetes (caja roja) es significativamente más alta que la mediana del grupo sin diabetes (caja amarilla). Además, el rango intercuartílico del grupo con diabetes se encuentra en un nivel considerablemente superior, lo que indica que los pacientes diabéticos tienden a tener niveles de glucosa persistentemente más altos. El grupo sin diabetes tiene valores más bajos y una distribución más estrecha, aunque con algunos valores atípicos.
BloodPressure vs Outcome
ggplot(df_capped, aes(x = factor(Outcome, labels = c("No diabetes", "Diabetes")),
y = BloodPressure,
fill = factor(Outcome))) +
geom_boxplot(outlier.shape = 21, outlier.fill = "white", outlier.color = "black", width = 0.5) +
scale_fill_manual(values = c("#FBD000", "red"),
name = "Diabetes",
labels = c("No", "Sí")) +
labs(
title = "Presión arterial por condición de diabetes",
x = "",
y = "Presión arterial (mmHg)"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
axis.text = element_text(color = "black"),
panel.grid.major = element_line(color = "gray80"),
panel.grid.minor = element_line(color = "gray90"),
legend.position = "top"
)
Interpretación
El boxplot de la presión arterial por condición de diabetes muestra que, aunque hay un solapamiento en las distribuciones, los pacientes con diabetes (caja roja) tienden a tener una presión arterial ligeramente más alta. La mediana de la presión arterial en el grupo diabético está un poco por encima de la del grupo no diabético. Sin embargo, el rango intercuartílico (la caja) y la dispersión total de los datos son similares en ambos grupos, lo que sugiere que la presión arterial tiene una asociación más débil con la diabetes en comparación con otras variables como la glucosa.
SkinThickness vs Outcome
ggplot(df_capped, aes(x = factor(Outcome, labels = c("No diabetes", "Diabetes")),
y = SkinThickness,
fill = factor(Outcome))) +
geom_boxplot(outlier.shape = 21, outlier.fill = "white", outlier.color = "black", width = 0.5) +
scale_fill_manual(values = c("#FBD000", "red"),
name = "Diabetes",
labels = c("No", "Sí")) +
labs(
title = "Grosor del pliegue cutáneo por condición de diabetes",
x = "",
y = "Grosor (mm)"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
axis.text = element_text(color = "black"),
panel.grid.major = element_line(color = "gray80"),
panel.grid.minor = element_line(color = "gray90"),
legend.position = "top"
)
Interpretación
El boxplot muestra que existe una asociación entre el grosor del pliegue cutáneo y la diabetes. El grupo de pacientes con diabetes (caja roja) tiene una mediana y un rango intercuartílico más altos en comparación con el grupo de pacientes sin diabetes (caja amarilla). Esto sugiere que un mayor grosor del pliegue cutáneo está asociado con la condición de diabetes.
BMI vs Outcome
ggplot(df_capped, aes(x = factor(Outcome, labels = c("No diabetes", "Diabetes")),
y = BMI,
fill = factor(Outcome))) +
geom_boxplot(outlier.shape = 21, outlier.fill = "white", outlier.color = "black", width = 0.5) +
scale_fill_manual(values = c("#FBD000", "red"),
name = "Diabetes",
labels = c("No", "Sí")) +
labs(
title = "BMI por condición de diabetes",
x = "",
y = "BMI"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
axis.text = element_text(color = "black"),
panel.grid.major = element_line(color = "gray80"),
panel.grid.minor = element_line(color = "gray90"),
legend.position = "top"
)
Interpretación
El boxplot del IMC (Índice de Masa Corporal) por condición de diabetes muestra una clara asociación entre ambas variables. La mediana del IMC es significativamente más alta en el grupo de pacientes con diabetes (caja roja) en comparación con el grupo sin diabetes (caja amarilla). Esto sugiere que un IMC más elevado es un factor de riesgo para el diagnóstico de la diabetes. Ambas distribuciones tienen una dispersión similar, pero la del grupo con diabetes se encuentra en un rango superior de valores.
DiabetesPedigreeFunction vs Outcome
ggplot(df_capped, aes(x = factor(Outcome, labels = c("No diabetes", "Diabetes")),
y = DiabetesPedigreeFunction,
fill = factor(Outcome))) +
geom_boxplot(outlier.shape = 21, outlier.fill = "white", outlier.color = "black", width = 0.5) +
scale_fill_manual(values = c("#FBD000", "red"),
name = "Diabetes",
labels = c("No", "Sí")) +
labs(
title = "Función de pedigrí de diabetes por condición",
x = "",
y = "Diabetes Pedigree Function"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
axis.text = element_text(color = "black"),
panel.grid.major = element_line(color = "gray80"),
panel.grid.minor = element_line(color = "gray90"),
legend.position = "top"
)
Interpretación
El boxplot de la Diabetes Pedigree Function muestra una clara asociación con el diagnóstico de diabetes. La mediana y el rango intercuartílico son significativamente más altos en el grupo de pacientes con diabetes (caja roja) en comparación con el grupo sin diabetes (caja amarilla). Esto indica que los pacientes con una mayor predisposición genética (valores más altos en esta función) tienen una mayor probabilidad de ser diagnosticados con diabetes.
Age vs Outcome
## Warning: package 'scales' was built under R version 4.4.1
##
## Adjuntando el paquete: 'scales'
## The following objects are masked from 'package:psych':
##
## alpha, rescale
df_capped$AgeGroup <- cut(df_capped$Age, breaks = seq(20, 90, by = 10), right = FALSE)
ggplot(df_capped, aes(x = AgeGroup, fill = factor(Outcome, labels = c("No", "Sí")))) +
geom_bar(position = "fill", color = "white", width = 0.7) +
scale_fill_manual(values = c("#FBD000", "red"),
name = "Diabetes") +
scale_y_continuous(labels = percent_format(accuracy = 1)) +
labs(
title = "Prevalencia de diabetes por grupo de edad",
x = "Grupo de edad",
y = "Proporción"
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
axis.text = element_text(color = "black"),
panel.grid.major = element_line(color = "gray80"),
panel.grid.minor = element_blank(),
legend.position = "top"
)
Interpretación
El gráfico de barras apiladas sobre la prevalencia de diabetes por grupo de edad muestra una clara asociación positiva entre la edad y el diagnóstico de diabetes. La proporción de pacientes con diabetes (barra roja) aumenta consistentemente a medida que aumenta el grupo de edad, pasando de ser menos del 25% en el grupo de 20-30 años, a más del 50% en los grupos de 40-60 años. Esto indica que la edad es un factor de riesgo significativo para el desarrollo de la diabetes en este conjunto de datos.
El análisis multivariado sirve para explorar las relaciones complejas entre múltiples variables al mismo tiempo, permitiendo simplificar los datos y hacer predicciones más precisas.
## Warning: package 'corrplot' was built under R version 4.4.3
## corrplot 0.95 loaded
cor_matrix <- cor(df_capped[, sapply(df_capped, is.numeric)])
corrplot(cor_matrix, method = "color",
col = colorRampPalette(c("red", "white", "#FBD000"))(20),
tl.col = "black", addCoef.col = "black")
Interpretación
El análisis exploratorio de datos reveló características clave en el conjunto de datos de diabetes. Primero, se observó que la variable objetivo, Outcome, está desbalanceada, con un 65% de pacientes sin diabetes y un 35% con la enfermedad. Este desequilibrio será un factor importante a considerar en la fase de modelado para evitar sesgos.
La mayoría de las variables predictoras, como Pregnancies, Glucose, Insulin, BMI, DiabetesPedigreeFunction y Age, presentan un sesgo positivo, indicando una alta concentración de valores en el extremo inferior y una cola larga de valores altos. Las distribuciones de Insulin y DiabetesPedigreeFunction son particularmente sesgadas y con valores atípicos (outliers), lo que justifica el uso de técnicas de preprocesamiento como el escalado o la transformación de datos. Por otro lado, variables como BloodPressure y SkinThickness muestran una distribución más cercana a la normal.
En cuanto a la correlación, los niveles de Glucose y el BMI son los predictores más fuertemente correlacionados con la diabetes. También se observaron relaciones importantes entre otras variables, como la fuerte correlación entre SkinThickness y BMI, y entre Pregnancies y Age. Sin embargo, en general, las correlaciones entre los predictores son de leves a moderadas, lo que minimiza el riesgo de multicolinealidad.
En resumen, el EDA ha proporcionado una comprensión profunda de la estructura de los datos, identificando la necesidad de manejar el desbalance de clases, el sesgo de algunas variables y la importancia de Glucose, Insulin, BMI y Age como predictores clave de la diabetes.