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
library(readxl)

DulcesM_M <- read_excel("DulcesM&M.xlsx")

head(DulcesM_M)
## # A tibble: 6 × 2
##   Color     Peso
##   <chr>    <dbl>
## 1 Rojo     0.751
## 2 Naranja  0.735
## 3 Amarillo 0.883
## 4 Café     0.696
## 5 Azul     0.881
## 6 Verde    0.925
  1. count: Cuenta las ocurrencias por grupo. Ideal para ver frecuencias de alguna variable categórica, como los colores en el dataset.
# Contamos la cantidad de dulces que hay de cada color
conteo_dulces <- count(DulcesM_M, Color)
conteo_dulces
## # A tibble: 6 × 2
##   Color        n
##   <chr>    <int>
## 1 Amarillo     8
## 2 Azul        27
## 3 Café         8
## 4 Naranja     25
## 5 Rojo        13
## 6 Verde       19
is.data.frame(conteo_dulces)
## [1] TRUE
table(DulcesM_M$Color)
## 
## Amarillo     Azul     Café  Naranja     Rojo    Verde 
##        8       27        8       25       13       19
is.table(table(DulcesM_M$Color))
## [1] TRUE
# table es una estructura diseñada específicamente para almacenar frecuencias de valores categóricos y suele convertirse fácilmente a vector, matriz o dataframe 
# con as.vector(), as.matrix(), as.dataframe()

as.matrix(table(DulcesM_M$Color))
##          [,1]
## Amarillo    8
## Azul       27
## Café        8
## Naranja    25
## Rojo       13
## Verde      19


  1. summarise: Genera resúmenes estadísticos. Permite calcular estadísticas como medias, varianzas o sumas, etc. facilitando el análisis de datos.
resumen <- summarise(DulcesM_M, 
                     Promedio = mean(Peso), 
                     Varianza = var(Peso), 
                     Desviación = sd(Peso),
                     Mediana = median(Peso),
                     Total = n())

resumen
## # A tibble: 1 × 5
##   Promedio Varianza Desviación Mediana Total
##      <dbl>    <dbl>      <dbl>   <dbl> <int>
## 1    0.853  0.00273     0.0523   0.856   100


  1. group_by: Agrupa el data frame por una o más variables. Cuando queremos realizar análisis estadístico por grupos, como promedio de peso por color.
grupo_colores <- group_by(DulcesM_M, Color)

resumen_color <- summarise(grupo_colores,
                           Promedio = mean(Peso), 
                     Varianza = var(Peso), 
                     Desviación = sd(Peso),
                     Mediana = median(Peso),
                     Total = n())

resumen_color
## # A tibble: 6 × 6
##   Color    Promedio Varianza Desviación Mediana Total
##   <chr>       <dbl>    <dbl>      <dbl>   <dbl> <int>
## 1 Amarillo    0.834  0.00156     0.0395   0.849     8
## 2 Azul        0.844  0.00183     0.0428   0.842    27
## 3 Café        0.848  0.00632     0.0795   0.857     8
## 4 Naranja     0.858  0.00251     0.0501   0.863    25
## 5 Rojo        0.864  0.00332     0.0576   0.859    13
## 6 Verde       0.864  0.00324     0.0570   0.865    19


  1. Piping (%>%). El operador %>% facilita la escritura fluida y clara de código en R, permitiendo encadenar operaciones sin necesidad de crear variables intermedias.
DulcesM_M %>% 
  group_by(Color) %>% 
  summarise(Promedio = mean(Peso),
            Varianza = var(Peso),
            Desviación = sd(Peso),
            Mediana = median(Peso),
            Total = n()) %>% 
  arrange(desc(Total)) %>% 
  print()
## # A tibble: 6 × 6
##   Color    Promedio Varianza Desviación Mediana Total
##   <chr>       <dbl>    <dbl>      <dbl>   <dbl> <int>
## 1 Azul        0.844  0.00183     0.0428   0.842    27
## 2 Naranja     0.858  0.00251     0.0501   0.863    25
## 3 Verde       0.864  0.00324     0.0570   0.865    19
## 4 Rojo        0.864  0.00332     0.0576   0.859    13
## 5 Amarillo    0.834  0.00156     0.0395   0.849     8
## 6 Café        0.848  0.00632     0.0795   0.857     8


Visualización con dplyr

  • Histograma

Un histograma es una gráfica que muestra la distribución de una variable numérica agrupando los datos en intervalos o bins.

La altura de cada barra representa la frecuencia o cantidad de observaciones dentro de cada intervalo.

Este tipo de gráfico permite visualizar la forma de la distribución de los datos, identificar concentraciones, dispersión y posibles asimetrías.

# Histograma de los pesos de los dulces

DulcesM_M$Peso %>% hist(col = "salmon",
                        xlab = "Peso gr",
                        ylab = "Frecuencia",
                        main = "Conteo pesos Dulces M&M")

# La mayor frecuencia de dulces tiene un peso entre 0.8 y 0.9 gramos.

# El intervalo de 0.85, 0.9 concentra la mayor cantidad de observaciones en tu muestra.

# Sugiere que los pesos de los M&M tienden a agruparse alrededor de ese rango.


  • Diagrama de caja y bigotes

Un diagrama de caja y bigotes (boxplot) es una gráfica que resume la distribución de una variable numérica.

La caja representa el 50% central de los datos entre el primer y el tercer cuartil, y la línea dentro de la caja indica la mediana.

Los bigotes se extienden hacia los valores más extremos no atípicos y los puntos fuera de ellos representan posibles valores atípicos.

Este gráfico permite visualizar rápidamente la dispersión y la presencia de valores extremos.

# Diagrama de caja y bigotes de pesos de los dulces

DulcesM_M %>% boxplot(Peso ~ Color,
                      data = .,
                      col = c("yellow1","skyblue2","chocolate",
                              "orange","red2","darkolivegreen2"),
                      xlab = "Colores",
                      ylab = "Peso",
                      main = "Caja bigotes por color")

# La tendencia central de la variable medida, peso, es prácticamente la misma para todos los colores.

# Para las cajas con bigotes más largos, interpretamos mayor variabilidad. Si nos centramos en los dulces verdes, observamos  mayor dispersión en los datos comparado con los otros colores.

# Por el contrario, para los dulces café el rango intercuartílico es menor, 
# lo que sugiere que los datos están más concentrados alrededor de la mediana.
# calcular mediana
mediana <- median(DulcesM_M$Peso)
DulcesM_M %>% boxplot(Peso ~ Color,
                      data = .,
                      col = c("yellow1","skyblue2","chocolate",
                              "orange","red2","darkolivegreen2"),
                      xlab = "Colores",
                      ylab = "Peso",
                      main = "Caja bigotes por color",
                      yaxt = "n")   # quitamos el eje Y automático

axis(2, at = seq(0.7, 1.1, by = 0.02))  # agregamos más marcas

# agregar linea horizontal en la mediana
abline(h = mediana, col = "blue", lwd = 2, lty = 3)

# abline puede añadir líneas horizontales, verticales o rectas a una gráfica existente.



Repaso biblioteca dplyr

Cargamos las librerías a utilizar

library(readxl) # Lectura de documentos de excel
library(dplyr) # Para acceder a sus funciones
library(tidyr) # Para la función drop_na

Importamos la base de datos a trabajar

diabetes <- read_excel("diabetes.xlsx")
head(diabetes)
## # A tibble: 6 × 19
##      id  chol stab.glu   hdl ratio glyhb location     age gender height weight
##   <dbl> <dbl>    <dbl> <dbl> <dbl> <dbl> <chr>      <dbl> <chr>   <dbl>  <dbl>
## 1  1000   203       82    56  3.60  4.31 Buckingham    46 female     62    121
## 2  1001   165       97    24  6.90  4.44 Buckingham    29 female     64    218
## 3  1002   228       92    37  6.20  4.64 Buckingham    58 female     61    256
## 4  1003    78       93    12  6.5   4.63 Buckingham    67 male       67    119
## 5  1005   249       90    28  8.90  7.72 Buckingham    64 male       68    183
## 6  1008   248       94    69  3.60  4.81 Buckingham    34 male       71    190
## # ℹ 8 more variables: frame <chr>, bp.1s <dbl>, bp.1d <dbl>, bp.2s <dbl>,
## #   bp.2d <dbl>, waist <dbl>, hip <dbl>, time.ppn <dbl>


Esta base es parte del repositorio faraway:

https://cran.r-project.org/web/packages/faraway/index.html

library(faraway)
## 
## Adjuntando el paquete: 'faraway'
## The following object is masked _by_ '.GlobalEnv':
## 
##     diabetes
head(faraway::diabetes)
##     id chol stab.glu hdl ratio glyhb   location age gender height weight  frame
## 1 1000  203       82  56   3.6  4.31 Buckingham  46 female     62    121 medium
## 2 1001  165       97  24   6.9  4.44 Buckingham  29 female     64    218  large
## 3 1002  228       92  37   6.2  4.64 Buckingham  58 female     61    256  large
## 4 1003   78       93  12   6.5  4.63 Buckingham  67   male     67    119  large
## 5 1005  249       90  28   8.9  7.72 Buckingham  64   male     68    183 medium
## 6 1008  248       94  69   3.6  4.81 Buckingham  34   male     71    190  large
##   bp.1s bp.1d bp.2s bp.2d waist hip time.ppn
## 1   118    59    NA    NA    29  38      720
## 2   112    68    NA    NA    46  48      360
## 3   190    92   185    92    49  57      180
## 4   110    50    NA    NA    33  38      480
## 5   138    80    NA    NA    44  41      300
## 6   132    86    NA    NA    36  42      195


La base de datos se conforma de las siguientes variables:

  • id → Identificación del paciente
  • chol → Colesterol total
  • stab.glu → Glucosa en sangre estabilizada
  • hdl → Colesterol HDL (lipoproteína de alta densidad)
  • ratio → Relación colesterol total/HDL
  • glyhb → Hemoglobina glicosilada (HbA1c), indicador del control de glucosa a largo plazo
  • location → Ubicación o centro donde se realizó la medición
  • age → Edad
  • gender → Género
  • height → Estatura
  • weight → Peso
  • frame → Complexión
  • bp.1s → Presión arterial sistólica (1ra medición)
  • bp.1d → Presión arterial diastólica (1ra medición)
  • bp.2s → Presión arterial sistólica (2da medición)
  • bp.2d → Presión arterial diastólica (2da medición)
  • waist → Circunferencia de la cintura
  • hip → Circunferencia de la cadera
  • time.ppn → Tiempo postprandial (minutos después de comer)


  • summarise: Genera resúmenes estadísticos.
resumen1 <- summarise(diabetes,
                      Total = n(),
                      Media = mean(age, na.rm = T),
                      Varianza = var(age, na.rm = T),
                      Desviación = sd(age, na.rm = T))

resumen1
## # A tibble: 1 × 4
##   Total Media Varianza Desviación
##   <int> <dbl>    <dbl>      <dbl>
## 1   403  46.9     266.       16.3
# ¿Qué tantos valores NA hay?
is.na(diabetes$chol)
##   [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [25] FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [37] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [49] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [61] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [73] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [85] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [97] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [109] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [121] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [133] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [145] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [157] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [169] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [181] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [193] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [205] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [217] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [229] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [241] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [253] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [265] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [277] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [289] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [301] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [313] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [325] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [337] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [349] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [361] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [373] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [385] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [397] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
total_na_colesterol <- summarise(diabetes,
                                 Total_NA = sum(is.na(chol)))
total_na_colesterol
## # A tibble: 1 × 1
##   Total_NA
##      <int>
## 1        1
# ¿En qué observación están los NA colesterol?
indice_NA_chol <- which(is.na(diabetes$chol)) 

indice_NA_chol
## [1] 28
diabetes[indice_NA_chol,]
## # A tibble: 1 × 19
##      id  chol stab.glu   hdl ratio glyhb location     age gender height weight
##   <dbl> <dbl>    <dbl> <dbl> <dbl> <dbl> <chr>      <dbl> <chr>   <dbl>  <dbl>
## 1  1281    NA       74    NA    NA  4.28 Buckingham    48 male       68    100
## # ℹ 8 more variables: frame <chr>, bp.1s <dbl>, bp.1d <dbl>, bp.2s <dbl>,
## #   bp.2d <dbl>, waist <dbl>, hip <dbl>, time.ppn <dbl>
# ¿Hay NA en la 1era medición de la presión arterial sistólica?
total_na_bp.1s <- summarise(diabetes,
                                 Total_NA = sum(is.na(bp.1s)))
total_na_bp.1s
## # A tibble: 1 × 1
##   Total_NA
##      <int>
## 1        5
# ¿En qué observación están los NA bp.1s?
indice_NA_bp.1s <- which(is.na(diabetes$bp.1s)) 

indice_NA_bp.1s
## [1]   8  14  38  64 216
diabetes[indice_NA_bp.1s,] # Num observacion != id paciente
## # A tibble: 5 × 19
##      id  chol stab.glu   hdl ratio glyhb location     age gender height weight
##   <dbl> <dbl>    <dbl> <dbl> <dbl> <dbl> <chr>      <dbl> <chr>   <dbl>  <dbl>
## 1  1015   227       75    44  5.20  3.94 Buckingham    37 male       59    170
## 2  1031   183       79    46  4     4.59 Louisa        40 female     59    165
## 3  1314   190      107    32  5.90  3.56 Buckingham    46 male       72    205
## 4  2780   145       85    29  5     3.99 Buckingham    38 female     NA    125
## 5 15805   197       92    46  4.30  4.75 Buckingham    36 female     64    136
## # ℹ 8 more variables: frame <chr>, bp.1s <dbl>, bp.1d <dbl>, bp.2s <dbl>,
## #   bp.2d <dbl>, waist <dbl>, hip <dbl>, time.ppn <dbl>


  • group_by: Agrupa el data frame por una o más variables.
diabetes %>% 
  group_by(gender) %>% 
  summarise(Total = n(),
            Media = round(mean(chol, na.rm = T),2),
            Q1 = quantile(chol, 0.25, na.rm = T),
            Mediana = quantile(chol, 0.5, na.rm = T),
            Q3 = quantile(chol, 0.75, na.rm = T),
            Var = var(chol, na.rm = T),
            Minimo = min(chol, na.rm = T),
            Maximo = max(chol, na.rm = T)) %>% 
  print()
## # A tibble: 2 × 9
##   gender Total Media    Q1 Mediana    Q3   Var Minimo Maximo
##   <chr>  <int> <dbl> <dbl>   <dbl> <dbl> <dbl>  <dbl>  <dbl>
## 1 female   234  208.   179    204.  230. 1914.    118    443
## 2 male     169  207.   179    204   230  2072.     78    404
# Si no muestra decimales, correr en consola la siguiente instrucción:
# options(pillar.sigfig = 6)
boxplot(diabetes$chol ~ diabetes$gender)


Missing values

Los valores faltantes o “missing values” son comunes en muchos conjuntos de datos y pueden influir negativamente en los análisis. En R, estos valores se representan como NA (Not Available).

Podemos identificar los id de las personas que tienen al menos un valor NA en cualquiera de sus variables o en una variable específica.

# Filtramos las filas con al menos un NA en alguna de las variables
filtrado_NA <- filter(diabetes, dplyr::if_any(tidyr::everything(), is.na))

filtrado_NA
## # A tibble: 273 × 19
##       id  chol stab.glu   hdl ratio glyhb location     age gender height weight
##    <dbl> <dbl>    <dbl> <dbl> <dbl> <dbl> <chr>      <dbl> <chr>   <dbl>  <dbl>
##  1  1000   203       82    56  3.60  4.31 Buckingham    46 female     62    121
##  2  1001   165       97    24  6.90  4.44 Buckingham    29 female     64    218
##  3  1003    78       93    12  6.5   4.63 Buckingham    67 male       67    119
##  4  1005   249       90    28  8.90  7.72 Buckingham    64 male       68    183
##  5  1008   248       94    69  3.60  4.81 Buckingham    34 male       71    190
##  6  1015   227       75    44  5.20  3.94 Buckingham    37 male       59    170
##  7  1022   263       89    40  6.60  5.78 Buckingham    55 female     63    202
##  8  1029   215      128    34  6.30  4.97 Louisa        38 female     58    195
##  9  1030   238       75    36  6.60  4.47 Louisa        27 female     60    170
## 10  1031   183       79    46  4     4.59 Louisa        40 female     59    165
## # ℹ 263 more rows
## # ℹ 8 more variables: frame <chr>, bp.1s <dbl>, bp.1d <dbl>, bp.2s <dbl>,
## #   bp.2d <dbl>, waist <dbl>, hip <dbl>, time.ppn <dbl>
# más de la mitad de los registros de la base tienen algún NA

Podemos eliminar / “remover” las filas que contienen valores NA. La función drop_na() de dplyr nos permite realizar esta acción.

diabetes1 <- diabetes %>% drop_na() %>% print()
## # A tibble: 130 × 19
##       id  chol stab.glu   hdl ratio glyhb location     age gender height weight
##    <dbl> <dbl>    <dbl> <dbl> <dbl> <dbl> <chr>      <dbl> <chr>   <dbl>  <dbl>
##  1  1002   228       92    37  6.20  4.64 Buckingham    58 female     61    256
##  2  1011   195       92    41  4.80  4.84 Buckingham    30 male       69    191
##  3  1016   177       87    49  3.60  4.84 Buckingham    45 male       69    166
##  4  1024   242       82    54  4.5   4.77 Louisa        60 female     65    156
##  5  1036   213       83    47  4.5   3.41 Louisa        33 female     65    157
##  6  1252   186       97    50  3.70  6.49 Buckingham    70 male       67    178
##  7  1253   234       65    76  3.10  4.67 Buckingham    47 male       67    230
##  8  1256   281       92    41  6.90  5.56 Buckingham    66 female     62    185
##  9  1271   228       66    45  5.10  4.61 Buckingham    24 female     61    113
## 10  1285   215       72    42  5.10  4.37 Louisa        40 male       70    189
## # ℹ 120 more rows
## # ℹ 8 more variables: frame <chr>, bp.1s <dbl>, bp.1d <dbl>, bp.2s <dbl>,
## #   bp.2d <dbl>, waist <dbl>, hip <dbl>, time.ppn <dbl>
# Si queremos eliminar los NA de una columna específica
# E.g. eliminamos los NA's de las columnas bp (blood pressure)
diabetes2 <- diabetes %>% 
  drop_na(bp.1s, bp.1d, bp.2s, bp.2d) %>% 
  print()
## # A tibble: 141 × 19
##       id  chol stab.glu   hdl ratio glyhb location     age gender height weight
##    <dbl> <dbl>    <dbl> <dbl> <dbl> <dbl> <chr>      <dbl> <chr>   <dbl>  <dbl>
##  1  1002   228       92    37  6.20  4.64 Buckingham    58 female     61    256
##  2  1011   195       92    41  4.80  4.84 Buckingham    30 male       69    191
##  3  1016   177       87    49  3.60  4.84 Buckingham    45 male       69    166
##  4  1024   242       82    54  4.5   4.77 Louisa        60 female     65    156
##  5  1036   213       83    47  4.5   3.41 Louisa        33 female     65    157
##  6  1252   186       97    50  3.70  6.49 Buckingham    70 male       67    178
##  7  1253   234       65    76  3.10  4.67 Buckingham    47 male       67    230
##  8  1256   281       92    41  6.90  5.56 Buckingham    66 female     62    185
##  9  1271   228       66    45  5.10  4.61 Buckingham    24 female     61    113
## 10  1285   215       72    42  5.10  4.37 Louisa        40 male       70    189
## # ℹ 131 more rows
## # ℹ 8 more variables: frame <chr>, bp.1s <dbl>, bp.1d <dbl>, bp.2s <dbl>,
## #   bp.2d <dbl>, waist <dbl>, hip <dbl>, time.ppn <dbl>


Podemos realizar la acción de imputar lo que significa reemplazar los valores faltantes (NA) con un valor estimado o razonable basado en los datos disponibles.

La imputación se usa para evitar la pérdida de información al eliminar filas completas con valores faltantes.

# Imputamos con MEDIA en un dataframe copia
diabetes3 <- diabetes
media_bp.1s <- mean(diabetes3$bp.1s, na.rm = TRUE)
diabetes3$bp.1s[is.na(diabetes3$bp.1s)] <- media_bp.1s

is.na(diabetes3$bp.1s)
##   [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [37] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [49] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [61] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [73] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [85] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [97] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [109] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [121] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [133] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [145] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [157] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [169] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [181] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [193] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [205] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [217] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [229] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [241] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [253] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [265] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [277] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [289] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [301] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [313] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [325] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [337] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [349] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [361] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [373] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [385] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [397] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
sum(is.na(diabetes3$bp.1s))
## [1] 0
hist(diabetes$bp.1s, breaks = 20)

hist(diabetes3$bp.1s, breaks = 20)


boxplot(diabetes$bp.1s)

# Identificamos la presencia de valores atípicos

Cuando hay valores atípicos (outliers), la mediana suele ser mejor que la media para imputar datos faltantes porque es más robusta frente a valores extremos.

La media se calcula usando todos los valores, por lo que un número muy grande o muy pequeño puede desplazar el promedio y hacerlo poco representativo del conjunto de datos.

En cambio, la mediana es el valor central cuando los datos se ordenan, por lo que no se ve afectada por la magnitud de los valores extremos, sino solo por su posición en el orden.

diabetes4 <- diabetes

mediana_bp.1s <- median(diabetes4$bp.1s, na.rm = TRUE)
diabetes4$bp.1s[is.na(diabetes4$bp.1s)] <- mediana_bp.1s

is.na(diabetes4$bp.1s)
##   [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [37] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [49] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [61] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [73] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [85] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
##  [97] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [109] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [121] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [133] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [145] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [157] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [169] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [181] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [193] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [205] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [217] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [229] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [241] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [253] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [265] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [277] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [289] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [301] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [313] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [325] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [337] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [349] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [361] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [373] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [385] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [397] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
sum(is.na(diabetes4$bp.1s))
## [1] 0
hist(diabetes$bp.1s, breaks = 20)

hist(diabetes4$bp.1s, breaks = 20)


Caso práctico: VIH

Una organización de salud pública está interesada en comprender los factores que influyen en los resultados de las pruebas de VIH y la prevalencia de educación sobre el SIDA entre diferentes grupos de población. Se requiere un análisis detallado para identificar patrones y áreas de enfoque para futuras campañas educativas y de salud.

library(readxl)
library(dplyr)
library(tidyr)
library(ggplot2)
HIV <- read_excel("HIV.xlsx")
head(HIV)
## # A tibble: 6 × 10
##     Age `Marital Staus` STD   `Educational Background` `HIV TEST IN PAST YEAR`
##   <dbl> <chr>           <chr> <chr>                    <chr>                  
## 1    12 UNMARRIED       NO    College Degree           NO                     
## 2    12 UNMARRIED       NO    Junior High School       NO                     
## 3    12 UNMARRIED       YES   Illiteracy               YES                    
## 4    12 UNMARRIED       YES   Junior High School       NO                     
## 5    12 UNMARRIED       YES   Junior High School       NO                     
## 6    12 UNMARRIED       YES   College Degree           YES                    
## # ℹ 5 more variables: `AIDS education` <chr>,
## #   `Places of seeking sex partners` <chr>, `SEXUAL ORIENTATION` <chr>,
## #   `Drug- taking` <chr>, Result <chr>


Análisis preliminar de datos

  1. Muestra un resumen estadístico general de la base de datos para la variable edad, clasificado por orientación sexual. Incluye:

o Número total de registros o Valor Mínimo o Media o Primer Cuartil o Mediana o Tercer Cuartil o Valor Máximo o Varianza o Desviación Estándar o Cantidad de valores NA

# ¿Cuántas orientaciones sexuales distintas hay en la base?
HIV %>%  
  group_by(`SEXUAL ORIENTATION`) %>% # Usamos backticks con AltGr + ] + SPACE
  count(`SEXUAL ORIENTATION`)
## # A tibble: 5 × 2
## # Groups:   SEXUAL ORIENTATION [5]
##   `SEXUAL ORIENTATION`     n
##   <chr>                <int>
## 1 BIsexual                 2
## 2 Bisexual               148
## 3 Heterosexual           370
## 4 Hetersexual              4
## 5 Homosexual             174
table(HIV$`SEXUAL ORIENTATION`)
## 
##     Bisexual     BIsexual Heterosexual  Hetersexual   Homosexual 
##          148            2          370            4          174


# Cambio en registro: hetersexual -> heterosexual
indice_hetersexual <- which(HIV$`SEXUAL ORIENTATION` == "Hetersexual")
indice_hetersexual
## [1] 139 304 431 473
HIV$`SEXUAL ORIENTATION`[indice_hetersexual]
## [1] "Hetersexual" "Hetersexual" "Hetersexual" "Hetersexual"
HIV1 <- HIV %>% 
  mutate(`SEXUAL ORIENTATION` = {
    x <- `SEXUAL ORIENTATION`
    x[x == "Hetersexual"] <- "Heterosexual"
    x
  })

which(HIV1$`SEXUAL ORIENTATION` == "Hetersexual")
## integer(0)
# replace(vector, condicion, valor_nuevo)
HIV1 <- HIV %>% 
  mutate(`SEXUAL ORIENTATION` = replace( 
    `SEXUAL ORIENTATION`,
    `SEXUAL ORIENTATION` == "Hetersexual",
    "Heterosexual"
  ))

which(HIV1$`SEXUAL ORIENTATION` == "Hetersexual")
## integer(0)
# recode(variable, valor_viejo = valor_nuevo)
HIV1 <- HIV %>% 
  mutate(`SEXUAL ORIENTATION` = recode( 
    `SEXUAL ORIENTATION`,
    "Hetersexual" = "Heterosexual"
  ))

which(HIV1$`SEXUAL ORIENTATION` == "Hetersexual")
## integer(0)
# Cambio en registro: BIsexual -> bisexual
indice_BIsexual <- which(HIV$`SEXUAL ORIENTATION` == "BIsexual")
indice_BIsexual
## [1] 262 511
HIV$`SEXUAL ORIENTATION`[indice_BIsexual]
## [1] "BIsexual" "BIsexual"
# replace(vector, condicion, valor_nuevo)
HIV1 <- HIV1 %>% 
  mutate(`SEXUAL ORIENTATION` = replace( 
    `SEXUAL ORIENTATION`,
    `SEXUAL ORIENTATION` == "BIsexual",
    "Bisexual"
  ))

which(HIV1$`SEXUAL ORIENTATION` == "Hetersexual")
## integer(0)
which(HIV1$`SEXUAL ORIENTATION` == "BIsexual")
## integer(0)
table(HIV1$`SEXUAL ORIENTATION`)
## 
##     Bisexual Heterosexual   Homosexual 
##          150          374          174
resumen <- HIV1 %>% 
  group_by(`SEXUAL ORIENTATION`) %>% 
  summarise(Total = n(),
            Minimo = min(Age, na.rm = T), 
            Media = mean(Age, na.rm = T),
            Q1 = quantile(Age, 0.25, na.rm = T),
            Mediana = median(Age, na.rm = T),
            Q3 = quantile(Age, 0.75, na.rm = T),
            Varianza = var(Age, na.rm = T),
            DS = sd(Age, na.rm = T),
            Valores_NA = sum(is.na(Age))) %>% 
  print()
## # A tibble: 3 × 10
##   `SEXUAL ORIENTATION` Total Minimo Media    Q1 Mediana    Q3 Varianza    DS
##   <chr>                <int>  <dbl> <dbl> <dbl>   <dbl> <dbl>    <dbl> <dbl>
## 1 Bisexual               150     12  38.1  30.2      37  45       130.  11.4
## 2 Heterosexual           374     12  37.5  30        37  44       145.  12.1
## 3 Homosexual             174     12  37.0  31        36  44.8     111.  10.6
## # ℹ 1 more variable: Valores_NA <int>
# Esquema real de con qué estamos trabajando