Reconocer diferencias entre datos: - Faltantes (NA) → no hay información disponible. - Erróneos o irreales → valores imposibles, inconsistentes o mal digitados (edad=-5, IMC=150). - Atípicos válidos → valores extremos pero posibles (altura = 195 cm, peso = 45 kg).
set.seed(123)
edad <- c(35,34,23,210,19,54,21,22,18,29,17,28,21,20,21,21,18,120) # 210 y 120
altura <- c(NA,165,NA,174,175,160,160,182,176,170,164,189,166,176,157,180,NA,158) # NA, 282
peso <- c(95,NA,64,79,70,60,50,97,59,68,52,98,51,73,52,65,58,180) # NA 180
genero <- c("M","F","F","M","M","F","F","M","M","M","F","M","F","M","F","M","F",NA)
#
BD <- data.frame(
genero = as.factor(genero),
edad, peso, altura,
IMC = peso / (altura/100)^2
)
#
BD
## genero edad peso altura IMC
## 1 M 35 95 NA NA
## 2 F 34 NA 165 NA
## 3 F 23 64 NA NA
## 4 M 210 79 174 26.09328
## 5 M 19 70 175 22.85714
## 6 F 54 60 160 23.43750
## 7 F 21 50 160 19.53125
## 8 M 22 97 182 29.28390
## 9 M 18 59 176 19.04700
## 10 M 29 68 170 23.52941
## 11 F 17 52 164 19.33373
## 12 M 28 98 189 27.43484
## 13 F 21 51 166 18.50777
## 14 M 20 73 176 23.56663
## 15 F 21 52 157 21.09619
## 16 M 21 65 180 20.06173
## 17 F 18 58 NA NA
## 18 <NA> 120 180 158 72.10383
# Identificar NA
colSums(is.na(BD)) # Numero de filas donde hay elementos NA
## genero edad peso altura IMC
## 1 0 1 3 4
# Faltantes a partir del resumen general
summary(BD)
## genero edad peso altura IMC
## F :8 Min. : 17.00 Min. : 50.00 Min. :157.0 Min. :18.51
## M :9 1st Qu.: 20.25 1st Qu.: 58.00 1st Qu.:162.0 1st Qu.:19.66
## NA's:1 Median : 21.50 Median : 65.00 Median :170.0 Median :23.15
## Mean : 40.61 Mean : 74.76 Mean :170.1 Mean :26.13
## 3rd Qu.: 32.75 3rd Qu.: 79.00 3rd Qu.:176.0 3rd Qu.:25.46
## Max. :210.00 Max. :180.00 Max. :189.0 Max. :72.10
## NA's :1 NA's :3 NA's :4
# Faltantes (solo numericas) uisando una libreria
# install.packages("skimr")
library(skimr)
skim(BD)
| Name | BD |
| Number of rows | 18 |
| Number of columns | 5 |
| _______________________ | |
| Column type frequency: | |
| factor | 1 |
| numeric | 4 |
| ________________________ | |
| Group variables | None |
Variable type: factor
| skim_variable | n_missing | complete_rate | ordered | n_unique | top_counts |
|---|---|---|---|---|---|
| genero | 1 | 0.94 | FALSE | 2 | M: 9, F: 8 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| edad | 0 | 1.00 | 40.61 | 48.63 | 17.00 | 20.25 | 21.50 | 32.75 | 210.0 | ▇▁▁▁▁ |
| peso | 1 | 0.94 | 74.76 | 31.41 | 50.00 | 58.00 | 65.00 | 79.00 | 180.0 | ▇▂▁▁▁ |
| altura | 3 | 0.83 | 170.13 | 9.66 | 157.00 | 162.00 | 170.00 | 176.00 | 189.0 | ▆▅▇▃▂ |
| IMC | 4 | 0.78 | 26.13 | 13.63 | 18.51 | 19.66 | 23.15 | 25.46 | 72.1 | ▇▁▁▁▁ |
# Atipicos por detección visual básica
par(mfrow=c(2,2))
boxplot(BD$edad, main="Edad (años)", horizontal = T)
boxplot(BD$altura, main="Altura (cm)", horizontal = T)
boxplot(BD$peso, main="Peso (Kg)", horizontal = T)
boxplot(BD$IMC, main="IMC", horizontal = T)
# Atipicos a partir de su variacion
# Regla de rango intercuartílico
Q1 <- quantile(BD$peso, 0.25, na.rm=TRUE)
Q1
## 25%
## 58
Q3 <- quantile(BD$peso, 0.75, na.rm=TRUE)
Q3
## 75%
## 79
IQR <- Q3 - Q1
IQR
## 75%
## 21
limite_inf <- Q1 - 1.5 * IQR
limite_inf
## 25%
## 26.5
limite_sup <- Q3 + 1.5 * IQR
limite_sup
## 75%
## 110.5
# Visualizamos los datos que aceptamos tomar
boxplot(BD$peso, main="Peso (Kg)", horizontal = T)
abline(v=Q1, col="red")
abline(v=Q3, col="red")
abline(v=limite_inf, col="lightblue")
abline(v=limite_sup, col="lightblue")
# Filtrar la base de datos (usando criterio de IQR)
BD2 <- subset(BD, peso>limite_inf & peso<limite_sup)
BD2
## genero edad peso altura IMC
## 1 M 35 95 NA NA
## 3 F 23 64 NA NA
## 4 M 210 79 174 26.09328
## 5 M 19 70 175 22.85714
## 6 F 54 60 160 23.43750
## 7 F 21 50 160 19.53125
## 8 M 22 97 182 29.28390
## 9 M 18 59 176 19.04700
## 10 M 29 68 170 23.52941
## 11 F 17 52 164 19.33373
## 12 M 28 98 189 27.43484
## 13 F 21 51 166 18.50777
## 14 M 20 73 176 23.56663
## 15 F 21 52 157 21.09619
## 16 M 21 65 180 20.06173
## 17 F 18 58 NA NA
BD3 <- subset(BD2, edad<100)
BD3
## genero edad peso altura IMC
## 1 M 35 95 NA NA
## 3 F 23 64 NA NA
## 5 M 19 70 175 22.85714
## 6 F 54 60 160 23.43750
## 7 F 21 50 160 19.53125
## 8 M 22 97 182 29.28390
## 9 M 18 59 176 19.04700
## 10 M 29 68 170 23.52941
## 11 F 17 52 164 19.33373
## 12 M 28 98 189 27.43484
## 13 F 21 51 166 18.50777
## 14 M 20 73 176 23.56663
## 15 F 21 52 157 21.09619
## 16 M 21 65 180 20.06173
## 17 F 18 58 NA NA
# Reemplazar NA de altura con media general (o por mediana?)
mean(BD$altura) # Media de la data original
## [1] NA
mean(BD$altura, na.rm=T) # promedieme sin los faltantes
## [1] 170.1333
#
BD4 <- BD # Copia de la BD original para no afectarla
BD4$altura[is.na(BD4$altura)] <- mean(BD4$altura, na.rm=TRUE)
BD4 # Visualizamos la base de datos imputada BD4
## genero edad peso altura IMC
## 1 M 35 95 170.1333 NA
## 2 F 34 NA 165.0000 NA
## 3 F 23 64 170.1333 NA
## 4 M 210 79 174.0000 26.09328
## 5 M 19 70 175.0000 22.85714
## 6 F 54 60 160.0000 23.43750
## 7 F 21 50 160.0000 19.53125
## 8 M 22 97 182.0000 29.28390
## 9 M 18 59 176.0000 19.04700
## 10 M 29 68 170.0000 23.52941
## 11 F 17 52 164.0000 19.33373
## 12 M 28 98 189.0000 27.43484
## 13 F 21 51 166.0000 18.50777
## 14 M 20 73 176.0000 23.56663
## 15 F 21 52 157.0000 21.09619
## 16 M 21 65 180.0000 20.06173
## 17 F 18 58 170.1333 NA
## 18 <NA> 120 180 158.0000 72.10383
mean(BD4$altura)
## [1] 170.1333
# Conclusion, completamos la data sin afectar la media del grupo
# Reemplazar NA de altura con media por grupos
# Usando funciones de base
BD_M <- subset(BD, genero=="M") # Igual que ==
BD_F <- subset(BD, genero!="M") # Diferente que !=
BD_M$altura[is.na(BD_M$altura)] <- mean(BD_M$altura, na.rm=TRUE)
BD_F$altura[is.na(BD_F$altura)] <- mean(BD_F$altura, na.rm=TRUE)
BD6 <- rbind(BD_M, BD_F)
BD6
## genero edad peso altura IMC
## 1 M 35 95 177.75 NA
## 4 M 210 79 174.00 26.09328
## 5 M 19 70 175.00 22.85714
## 8 M 22 97 182.00 29.28390
## 9 M 18 59 176.00 19.04700
## 10 M 29 68 170.00 23.52941
## 12 M 28 98 189.00 27.43484
## 14 M 20 73 176.00 23.56663
## 16 M 21 65 180.00 20.06173
## 2 F 34 NA 165.00 NA
## 3 F 23 64 162.00 NA
## 6 F 54 60 160.00 23.43750
## 7 F 21 50 160.00 19.53125
## 11 F 17 52 164.00 19.33373
## 13 F 21 51 166.00 18.50777
## 15 F 21 52 157.00 21.09619
## 17 F 18 58 162.00 NA
# Usando libreria dplyr
library(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
BD5 <- BD %>%
group_by(genero) %>%
mutate(altura2 = ifelse(is.na(altura), mean(altura, na.rm=TRUE), altura)
)
BD5
## # A tibble: 18 × 6
## # Groups: genero [3]
## genero edad peso altura IMC altura2
## <fct> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 M 35 95 NA NA 178.
## 2 F 34 NA 165 NA 165
## 3 F 23 64 NA NA 162
## 4 M 210 79 174 26.1 174
## 5 M 19 70 175 22.9 175
## 6 F 54 60 160 23.4 160
## 7 F 21 50 160 19.5 160
## 8 M 22 97 182 29.3 182
## 9 M 18 59 176 19.0 176
## 10 M 29 68 170 23.5 170
## 11 F 17 52 164 19.3 164
## 12 M 28 98 189 27.4 189
## 13 F 21 51 166 18.5 166
## 14 M 20 73 176 23.6 176
## 15 F 21 52 157 21.1 157
## 16 M 21 65 180 20.1 180
## 17 F 18 58 NA NA 162
## 18 <NA> 120 180 158 72.1 158
# Regla 20% de datos faltantes, es posible imputar
library(mice) # Multivariate Imputation by Chained Equations
##
## Adjuntando el paquete: 'mice'
## The following object is masked from 'package:stats':
##
## filter
## The following objects are masked from 'package:base':
##
## cbind, rbind
md.pattern(BD)
## edad genero peso altura IMC
## 13 1 1 1 1 1 0
## 3 1 1 1 0 0 2
## 1 1 1 0 1 0 2
## 1 1 0 1 1 1 1
## 0 1 1 3 4 9
# Realizamos la imputacion
imp <- mice(BD, m=3, method='pmm', seed=500)
##
## iter imp variable
## 1 1 genero peso altura IMC
## 1 2 genero peso altura IMC
## 1 3 genero peso altura IMC
## 2 1 genero peso altura IMC
## 2 2 genero peso altura IMC
## 2 3 genero peso altura IMC
## 3 1 genero peso altura IMC
## 3 2 genero peso altura IMC
## 3 3 genero peso altura IMC
## 4 1 genero peso altura IMC
## 4 2 genero peso altura IMC
## 4 3 genero peso altura IMC
## 5 1 genero peso altura IMC
## 5 2 genero peso altura IMC
## 5 3 genero peso altura IMC
## m=3: número de imputaciones.
## method='pmm': predictive mean matching (variables numéricas).
BD7 <- complete(imp)
# Verificamos los datos imputados
md.pattern(BD7)
## /\ /\
## { `---' }
## { O O }
## ==> V <== No need for mice. This data set is completely observed.
## \ \|/ /
## `-----'
## genero edad peso altura IMC
## 18 1 1 1 1 1 0
## 0 0 0 0 0 0
#
cor(BD[2:4])
## edad peso altura
## edad 1 NA NA
## peso NA 1 NA
## altura NA NA 1
cor(BD7[2:4])
## edad peso altura
## edad 1.0000000 0.45079944 -0.07951770
## peso 0.4507994 1.00000000 0.09544009
## altura -0.0795177 0.09544009 1.00000000
# Comparamos los datos imputados vs originales incompletos
summary(BD6) # Imputada. IMC 72? -> no filtrado previo
## genero edad peso altura IMC
## F:8 Min. : 17.00 Min. :50.00 Min. :157.0 Min. :18.51
## M:9 1st Qu.: 20.00 1st Qu.:56.50 1st Qu.:162.0 1st Qu.:19.53
## Median : 21.00 Median :64.50 Median :170.0 Median :22.86
## Mean : 35.94 Mean :68.19 Mean :170.3 Mean :22.60
## 3rd Qu.: 29.00 3rd Qu.:74.50 3rd Qu.:176.0 3rd Qu.:23.57
## Max. :210.00 Max. :98.00 Max. :189.0 Max. :29.28
## NA's :1 NA's :4
summary(BD)
## genero edad peso altura IMC
## F :8 Min. : 17.00 Min. : 50.00 Min. :157.0 Min. :18.51
## M :9 1st Qu.: 20.25 1st Qu.: 58.00 1st Qu.:162.0 1st Qu.:19.66
## NA's:1 Median : 21.50 Median : 65.00 Median :170.0 Median :23.15
## Mean : 40.61 Mean : 74.76 Mean :170.1 Mean :26.13
## 3rd Qu.: 32.75 3rd Qu.: 79.00 3rd Qu.:176.0 3rd Qu.:25.46
## Max. :210.00 Max. :180.00 Max. :189.0 Max. :72.10
## NA's :1 NA's :3 NA's :4