1 Introducción

El presente documento en formato R Markdown desarrolla una revisión integral de la base de datos Sleep_health_and_lifestyle_dataset.csv. En primer lugar, se realiza una revisión de las variables con el fin de identificar su naturaleza, su utilidad analítica y los ajustes previos necesarios para su adecuada interpretación. Posteriormente, se construyen las visualizaciones recomendadas para cada variable usando ggplot2, acompañadas de una interpretación orientada al análisis estadístico. En una sección independiente se incorporan los análisis de normalidad mediante la prueba de Shapiro-Wilk y gráficos QQ para las variables cuantitativas pertinentes. Finalmente, se propone una sección de modelado con variables respuesta y explicativas coherentes con la estructura de la base y con el contexto del problema.

2 Carga de datos y preparación inicial

library(ggplot2)

datos <- read.csv("Sleep_health_and_lifestyle_dataset.csv")

str(datos)
## 'data.frame':    374 obs. of  13 variables:
##  $ Person.ID              : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ Gender                 : chr  "Male" "Male" "Male" "Male" ...
##  $ Age                    : int  27 28 28 28 28 28 29 29 29 29 ...
##  $ Occupation             : chr  "Software Engineer" "Doctor" "Doctor" "Sales Representative" ...
##  $ Sleep.Duration         : num  6.1 6.2 6.2 5.9 5.9 5.9 6.3 7.8 7.8 7.8 ...
##  $ Quality.of.Sleep       : int  6 6 6 4 4 4 6 7 7 7 ...
##  $ Physical.Activity.Level: int  42 60 60 30 30 30 40 75 75 75 ...
##  $ Stress.Level           : int  6 8 8 8 8 8 7 6 6 6 ...
##  $ BMI.Category           : chr  "Overweight" "Normal" "Normal" "Obese" ...
##  $ Blood.Pressure         : chr  "126/83" "125/80" "125/80" "140/90" ...
##  $ Heart.Rate             : int  77 75 75 85 85 85 82 70 70 70 ...
##  $ Daily.Steps            : int  4200 10000 10000 3000 3000 3000 3500 8000 8000 8000 ...
##  $ Sleep.Disorder         : chr  "None" "None" "None" "Sleep Apnea" ...
head(datos)
##   Person.ID Gender Age           Occupation Sleep.Duration Quality.of.Sleep
## 1         1   Male  27    Software Engineer            6.1                6
## 2         2   Male  28               Doctor            6.2                6
## 3         3   Male  28               Doctor            6.2                6
## 4         4   Male  28 Sales Representative            5.9                4
## 5         5   Male  28 Sales Representative            5.9                4
## 6         6   Male  28    Software Engineer            5.9                4
##   Physical.Activity.Level Stress.Level BMI.Category Blood.Pressure Heart.Rate
## 1                      42            6   Overweight         126/83         77
## 2                      60            8       Normal         125/80         75
## 3                      60            8       Normal         125/80         75
## 4                      30            8        Obese         140/90         85
## 5                      30            8        Obese         140/90         85
## 6                      30            8        Obese         140/90         85
##   Daily.Steps Sleep.Disorder
## 1        4200           None
## 2       10000           None
## 3       10000           None
## 4        3000    Sleep Apnea
## 5        3000    Sleep Apnea
## 6        3000       Insomnia
summary(datos)
##    Person.ID         Gender               Age         Occupation       
##  Min.   :  1.00   Length:374         Min.   :27.00   Length:374        
##  1st Qu.: 94.25   Class :character   1st Qu.:35.25   Class :character  
##  Median :187.50   Mode  :character   Median :43.00   Mode  :character  
##  Mean   :187.50                      Mean   :42.18                     
##  3rd Qu.:280.75                      3rd Qu.:50.00                     
##  Max.   :374.00                      Max.   :59.00                     
##  Sleep.Duration  Quality.of.Sleep Physical.Activity.Level  Stress.Level  
##  Min.   :5.800   Min.   :4.000    Min.   :30.00           Min.   :3.000  
##  1st Qu.:6.400   1st Qu.:6.000    1st Qu.:45.00           1st Qu.:4.000  
##  Median :7.200   Median :7.000    Median :60.00           Median :5.000  
##  Mean   :7.132   Mean   :7.313    Mean   :59.17           Mean   :5.385  
##  3rd Qu.:7.800   3rd Qu.:8.000    3rd Qu.:75.00           3rd Qu.:7.000  
##  Max.   :8.500   Max.   :9.000    Max.   :90.00           Max.   :8.000  
##  BMI.Category       Blood.Pressure       Heart.Rate     Daily.Steps   
##  Length:374         Length:374         Min.   :65.00   Min.   : 3000  
##  Class :character   Class :character   1st Qu.:68.00   1st Qu.: 5600  
##  Mode  :character   Mode  :character   Median :70.00   Median : 7000  
##                                        Mean   :70.17   Mean   : 6817  
##                                        3rd Qu.:72.00   3rd Qu.: 8000  
##                                        Max.   :86.00   Max.   :10000  
##  Sleep.Disorder    
##  Length:374        
##  Class :character  
##  Mode  :character  
##                    
##                    
## 

2.1 Limpieza y transformaciones básicas

# La variable Sleep Disorder contiene valores faltantes. En esta base se asumirán
# como ausencia de trastorno del sueño.
datos$Sleep.Disorder[is.na(datos$Sleep.Disorder)] <- "No Disorder"
datos$Sleep.Disorder <- as.factor(datos$Sleep.Disorder)

# Unificación de categorías de BMI Category
datos$BMI.Category[datos$BMI.Category == "Normal Weight"] <- "Normal"
datos$BMI.Category <- as.factor(datos$BMI.Category)

# Separación de la presión arterial en sistólica y diastólica
bp_split <- strsplit(as.character(datos$Blood.Pressure), "/")
datos$Systolic <- as.numeric(sapply(bp_split, `[`, 1))
datos$Diastolic <- as.numeric(sapply(bp_split, `[`, 2))

# Variable binaria auxiliar para modelado logístico
# 0 = No Disorder, 1 = presenta algún trastorno
datos$Sleep.Disorder.Binary <- ifelse(datos$Sleep.Disorder == "No Disorder", 0, 1)
datos$Sleep.Disorder.Binary <- as.factor(datos$Sleep.Disorder.Binary)

# Estructura final
str(datos)
## 'data.frame':    374 obs. of  16 variables:
##  $ Person.ID              : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ Gender                 : chr  "Male" "Male" "Male" "Male" ...
##  $ Age                    : int  27 28 28 28 28 28 29 29 29 29 ...
##  $ Occupation             : chr  "Software Engineer" "Doctor" "Doctor" "Sales Representative" ...
##  $ Sleep.Duration         : num  6.1 6.2 6.2 5.9 5.9 5.9 6.3 7.8 7.8 7.8 ...
##  $ Quality.of.Sleep       : int  6 6 6 4 4 4 6 7 7 7 ...
##  $ Physical.Activity.Level: int  42 60 60 30 30 30 40 75 75 75 ...
##  $ Stress.Level           : int  6 8 8 8 8 8 7 6 6 6 ...
##  $ BMI.Category           : Factor w/ 3 levels "Normal","Obese",..: 3 1 1 2 2 2 2 1 1 1 ...
##  $ Blood.Pressure         : chr  "126/83" "125/80" "125/80" "140/90" ...
##  $ Heart.Rate             : int  77 75 75 85 85 85 82 70 70 70 ...
##  $ Daily.Steps            : int  4200 10000 10000 3000 3000 3000 3500 8000 8000 8000 ...
##  $ Sleep.Disorder         : Factor w/ 3 levels "Insomnia","None",..: 2 2 2 3 3 1 1 2 2 2 ...
##  $ Systolic               : num  126 125 125 140 140 140 140 120 120 120 ...
##  $ Diastolic              : num  83 80 80 90 90 90 90 80 80 80 ...
##  $ Sleep.Disorder.Binary  : Factor w/ 1 level "1": 1 1 1 1 1 1 1 1 1 1 ...
# Función auxiliar para construir tablas con frecuencia, proporción y etiqueta
preparar_pastel <- function(x) {
  tab <- as.data.frame(table(x))
  colnames(tab) <- c("Categoria", "Frecuencia")
  tab$Proporcion <- tab$Frecuencia / sum(tab$Frecuencia)
  tab$Porcentaje <- round(tab$Proporcion * 100, 1)
  tab$Etiqueta <- paste0(tab$Porcentaje, "%")
  tab
}

3 Revisión de las variables

A continuación se presenta una revisión general de las variables con su tipo y observaciones analíticas principales.

revision_variables <- data.frame(
  Variable = c(
    "Person ID", "Gender", "Age", "Occupation", "Sleep Duration",
    "Quality of Sleep", "Physical Activity Level", "Stress Level",
    "BMI Category", "Blood Pressure", "Heart Rate", "Daily Steps",
    "Sleep Disorder", "Systolic", "Diastolic", "Sleep Disorder Binary"
  ),
  Tipo = c(
    "Identificador", "Categórica nominal", "Cuantitativa discreta",
    "Categórica nominal", "Cuantitativa continua",
    "Cuantitativa discreta/ordinal", "Cuantitativa discreta",
    "Cuantitativa discreta/ordinal", "Categórica nominal",
    "Texto compuesto", "Cuantitativa discreta", "Cuantitativa discreta",
    "Categórica nominal", "Cuantitativa discreta", "Cuantitativa discreta",
    "Categórica binaria"
  ),
  Observacion = c(
    "Sirve como identificador; no se recomienda para análisis sustantivo.",
    "Permite comparaciones por género.",
    "Adecuada para análisis descriptivo y relaciones con sueño y presión arterial.",
    "Útil para comparaciones entre grupos ocupacionales.",
    "Variable central del estudio; se relaciona con estrés y calidad del sueño.",
    "Puede ser tratada como ordinal o numérica discreta.",
    "Permite analizar el comportamiento físico diario.",
    "Variable de interés por su relación con salud y sueño.",
    "Conviene unificar categorías antes del análisis.",
    "Debe descomponerse en sistólica y diastólica.",
    "Indica condición fisiológica relevante.",
    "Aproxima el nivel de actividad cotidiana.",
    "Se sustituyen los NA por 'No Disorder' para facilitar el análisis.",
    "Derivada de Blood Pressure para análisis cuantitativo.",
    "Derivada de Blood Pressure para análisis cuantitativo.",
    "Variable auxiliar para regresión logística binaria."
  ),
  stringsAsFactors = FALSE
)

revision_variables
##                   Variable                          Tipo
## 1                Person ID                 Identificador
## 2                   Gender            Categórica nominal
## 3                      Age         Cuantitativa discreta
## 4               Occupation            Categórica nominal
## 5           Sleep Duration         Cuantitativa continua
## 6         Quality of Sleep Cuantitativa discreta/ordinal
## 7  Physical Activity Level         Cuantitativa discreta
## 8             Stress Level Cuantitativa discreta/ordinal
## 9             BMI Category            Categórica nominal
## 10          Blood Pressure               Texto compuesto
## 11              Heart Rate         Cuantitativa discreta
## 12             Daily Steps         Cuantitativa discreta
## 13          Sleep Disorder            Categórica nominal
## 14                Systolic         Cuantitativa discreta
## 15               Diastolic         Cuantitativa discreta
## 16   Sleep Disorder Binary            Categórica binaria
##                                                                      Observacion
## 1           Sirve como identificador; no se recomienda para análisis sustantivo.
## 2                                              Permite comparaciones por género.
## 3  Adecuada para análisis descriptivo y relaciones con sueño y presión arterial.
## 4                            Útil para comparaciones entre grupos ocupacionales.
## 5     Variable central del estudio; se relaciona con estrés y calidad del sueño.
## 6                            Puede ser tratada como ordinal o numérica discreta.
## 7                              Permite analizar el comportamiento físico diario.
## 8                         Variable de interés por su relación con salud y sueño.
## 9                               Conviene unificar categorías antes del análisis.
## 10                                 Debe descomponerse en sistólica y diastólica.
## 11                                       Indica condición fisiológica relevante.
## 12                                     Aproxima el nivel de actividad cotidiana.
## 13            Se sustituyen los NA por 'No Disorder' para facilitar el análisis.
## 14                        Derivada de Blood Pressure para análisis cuantitativo.
## 15                        Derivada de Blood Pressure para análisis cuantitativo.
## 16                           Variable auxiliar para regresión logística binaria.

3.1 Comentario general sobre la revisión

La variable Person ID cumple una función exclusivamente identificadora y, por tanto, no debe emplearse como variable explicativa ni como variable respuesta en modelos estadísticos. Las variables Gender, Occupation, BMI Category y Sleep Disorder son categóricas y resultan apropiadas para análisis de frecuencias, proporciones y asociaciones. Por su parte, Age, Sleep Duration, Quality of Sleep, Physical Activity Level, Stress Level, Heart Rate y Daily Steps permiten análisis descriptivos cuantitativos, evaluación de normalidad y modelado. Finalmente, Blood Pressure requiere una transformación previa, pues su estructura original no es adecuada para análisis numérico directo; por ello se descompone en Systolic y Diastolic.

4 Visualizaciones recomendadas e interpretación

4.1 1. Person ID

La variable Person ID es un identificador. No se recomienda construir gráficos analíticos con ella, ya que su función es únicamente distinguir registros. Su utilidad radica en la detección de duplicados y en la trazabilidad de observaciones.

# Verificación simple de duplicados en el identificador
sum(duplicated(datos$Person.ID))
## [1] 0

Interpretación: si el valor anterior es mayor que cero, existirían identificadores repetidos, lo cual ameritaría una revisión de calidad de datos.

4.2 2. Gender

La variable Gender es categórica nominal. Las visualizaciones más adecuadas son el gráfico de barras, el gráfico de pastel y las barras apiladas con otra variable categórica.

ggplot(datos, aes(x = Gender)) +
  geom_bar(fill = "steelblue", color = "black") +
  labs(title = "Distribución de Gender",
       x = "Género", y = "Frecuencia") +
  theme_minimal()

Interpretación: este gráfico permite identificar la composición de la muestra según género y verificar si existe equilibrio o predominio de alguna categoría.

tabla_gender <- preparar_pastel(datos$Gender)

ggplot(tabla_gender, aes(x = "", y = Proporcion, fill = Categoria)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar(theta = "y") +
  geom_text(aes(label = Etiqueta),
            position = position_stack(vjust = 0.5), size = 4) +
  labs(title = "Proporción de Gender", fill = "Género") +
  theme_void()

Interpretación: resume la participación relativa de cada género dentro del conjunto de datos; cada sector muestra directamente el porcentaje correspondiente.

ggplot(datos, aes(x = Gender, fill = Sleep.Disorder)) +
  geom_bar(position = "fill") +
  labs(title = "Proporción de Sleep Disorder según Gender",
       x = "Género", y = "Proporción", fill = "Sleep Disorder") +
  theme_minimal()

Interpretación: permite examinar cómo cambia la proporción de trastornos del sueño dentro de cada grupo de género.

4.3 3. Age

La variable Age es cuantitativa discreta. Se recomienda representarla con histograma, boxplot, densidad y gráficos comparativos por grupos.

ggplot(datos, aes(x = Age)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Distribución de Age", x = "Edad", y = "Frecuencia") +
  theme_minimal()

Interpretación: permite observar la concentración de edades, la forma de la distribución y posibles agrupamientos.

ggplot(datos, aes(y = Age)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Age", y = "Edad") +
  theme_minimal()

Interpretación: resume la posición central, la dispersión y la presencia de posibles valores atípicos.

ggplot(datos, aes(x = Age)) +
  geom_density(fill = "orange", alpha = 0.4) +
  labs(title = "Densidad de Age", x = "Edad", y = "Densidad") +
  theme_minimal()

Interpretación: suaviza la distribución y facilita la identificación de asimetrías.

ggplot(datos, aes(x = Gender, y = Age, fill = Gender)) +
  geom_boxplot() +
  labs(title = "Age por Gender", x = "Género", y = "Edad") +
  theme_minimal()

Interpretación: permite comparar la distribución de la edad según género.

4.4 4. Occupation

La variable Occupation es categórica nominal con varias categorías, por lo que conviene emplear gráficos de barras horizontales, barras ordenadas y análisis cruzados con otras variables categóricas.

ggplot(datos, aes(x = Occupation)) +
  geom_bar(fill = "steelblue", color = "black") +
  coord_flip() +
  labs(title = "Frecuencia de Occupation",
       x = "Ocupación", y = "Frecuencia") +
  theme_minimal()

Interpretación: facilita la lectura de categorías cuando las etiquetas son largas o numerosas.

frecuencias_ocup <- table(datos$Occupation)
niveles_ordenados <- names(sort(frecuencias_ocup, decreasing = TRUE))
datos$Occupation.Ordenada <- factor(datos$Occupation, levels = niveles_ordenados)

ggplot(datos, aes(x = Occupation.Ordenada)) +
  geom_bar(fill = "darkcyan", color = "black") +
  coord_flip() +
  labs(title = "Occupation ordenada por frecuencia",
       x = "Ocupación", y = "Frecuencia") +
  theme_minimal()

Interpretación: muestra cuáles ocupaciones tienen mayor y menor presencia en la muestra.

ggplot(datos, aes(x = Occupation.Ordenada, fill = Gender)) +
  geom_bar(position = "fill") +
  coord_flip() +
  labs(title = "Proporción de Gender según Occupation",
       x = "Ocupación", y = "Proporción", fill = "Género") +
  theme_minimal()

Interpretación: evidencia la composición proporcional por género dentro de cada ocupación.

tabla_ocup_gender <- as.data.frame(table(datos$Occupation, datos$Gender))
colnames(tabla_ocup_gender) <- c("Occupation", "Gender", "Frecuencia")

ggplot(tabla_ocup_gender, aes(x = Gender, y = Occupation, fill = Frecuencia)) +
  geom_tile(color = "white") +
  labs(title = "Mapa de calor: Occupation vs Gender",
       x = "Género", y = "Ocupación", fill = "Frecuencia") +
  theme_minimal()

Interpretación: proporciona una lectura rápida de la concentración de frecuencias entre ocupación y género.

4.5 5. Sleep Duration

La variable Sleep Duration es cuantitativa continua. Se recomienda trabajar con histograma, boxplot, densidad y gráficos de dispersión.

ggplot(datos, aes(x = Sleep.Duration)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Distribución de Sleep Duration",
       x = "Horas de sueño", y = "Frecuencia") +
  theme_minimal()

Interpretación: permite identificar el rango habitual de duración del sueño en la muestra.

ggplot(datos, aes(y = Sleep.Duration)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Sleep Duration", y = "Horas de sueño") +
  theme_minimal()

Interpretación: resume la mediana, la variabilidad y la presencia de observaciones extremas.

ggplot(datos, aes(x = Sleep.Duration)) +
  geom_density(fill = "orange", alpha = 0.4) +
  labs(title = "Densidad de Sleep Duration",
       x = "Horas de sueño", y = "Densidad") +
  theme_minimal()

Interpretación: ayuda a establecer si la distribución es aproximadamente simétrica o si presenta sesgo.

ggplot(datos, aes(x = Gender, y = Sleep.Duration, fill = Gender)) +
  geom_boxplot() +
  labs(title = "Sleep Duration por Gender",
       x = "Género", y = "Horas de sueño") +
  theme_minimal()

Interpretación: compara la duración del sueño entre grupos de género.

ggplot(datos, aes(x = Sleep.Duration, y = Stress.Level)) +
  geom_point(color = "blue") +
  labs(title = "Sleep Duration vs Stress Level",
       x = "Horas de sueño", y = "Nivel de estrés") +
  theme_minimal()

Interpretación: permite explorar la relación esperada entre menor sueño y mayor estrés.

4.6 6. Quality of Sleep

La variable Quality of Sleep puede tratarse como cuantitativa discreta u ordinal. Se recomiendan gráficos de barras, histograma, boxplot y dispersiones con variables relacionadas.

ggplot(datos, aes(x = factor(Quality.of.Sleep))) +
  geom_bar(fill = "steelblue", color = "black") +
  labs(title = "Frecuencia de Quality of Sleep",
       x = "Nivel de calidad del sueño", y = "Frecuencia") +
  theme_minimal()

Interpretación: permite conocer qué niveles de calidad del sueño predominan en la base.

ggplot(datos, aes(x = Quality.of.Sleep)) +
  geom_histogram(bins = 8, fill = "skyblue", color = "black") +
  labs(title = "Distribución de Quality of Sleep",
       x = "Calidad del sueño", y = "Frecuencia") +
  theme_minimal()

Interpretación: muestra la forma general de la distribución.

ggplot(datos, aes(y = Quality.of.Sleep)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Quality of Sleep", y = "Calidad del sueño") +
  theme_minimal()

Interpretación: resume posición central y variabilidad de la calidad del sueño.

ggplot(datos, aes(x = Gender, y = Quality.of.Sleep, fill = Gender)) +
  geom_boxplot() +
  labs(title = "Quality of Sleep por Gender",
       x = "Género", y = "Calidad del sueño") +
  theme_minimal()

Interpretación: permite evaluar si la calidad del sueño cambia entre géneros.

ggplot(datos, aes(x = Sleep.Duration, y = Quality.of.Sleep)) +
  geom_point(color = "darkblue") +
  labs(title = "Sleep Duration vs Quality of Sleep",
       x = "Horas de sueño", y = "Calidad del sueño") +
  theme_minimal()

Interpretación: se espera una asociación positiva, de modo que una mayor duración del sueño tienda a relacionarse con mejor calidad percibida.

4.7 7. Physical Activity Level

La variable Physical Activity Level es cuantitativa discreta. Se recomienda representar su distribución y sus relaciones con pasos diarios y sueño.

ggplot(datos, aes(x = Physical.Activity.Level)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Distribución de Physical Activity Level",
       x = "Nivel de actividad física", y = "Frecuencia") +
  theme_minimal()

Interpretación: describe cómo se distribuyen los niveles de actividad física en la muestra.

ggplot(datos, aes(x = factor(Physical.Activity.Level))) +
  geom_bar(fill = "steelblue", color = "black") +
  labs(title = "Frecuencia de Physical Activity Level",
       x = "Nivel de actividad física", y = "Frecuencia") +
  theme_minimal()

Interpretación: es útil cuando se desea tratar la variable como discreta con pocos niveles observados.

ggplot(datos, aes(y = Physical.Activity.Level)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Physical Activity Level",
       y = "Nivel de actividad física") +
  theme_minimal()

Interpretación: resume mediana, dispersión y posibles valores extremos.

ggplot(datos, aes(x = Gender, y = Physical.Activity.Level, fill = Gender)) +
  geom_boxplot() +
  labs(title = "Physical Activity Level por Gender",
       x = "Género", y = "Nivel de actividad física") +
  theme_minimal()

Interpretación: compara la actividad física entre géneros.

ggplot(datos, aes(x = Physical.Activity.Level, y = Daily.Steps)) +
  geom_point(color = "blue") +
  labs(title = "Physical Activity Level vs Daily Steps",
       x = "Nivel de actividad física", y = "Pasos diarios") +
  theme_minimal()

Interpretación: se espera una relación positiva entre el nivel de actividad física y los pasos diarios.

4.8 8. Stress Level

La variable Stress Level es cuantitativa discreta con interpretación ordinal. Se recomienda combinar barras, histograma, boxplot y dispersiones.

ggplot(datos, aes(x = factor(Stress.Level))) +
  geom_bar(fill = "steelblue", color = "black") +
  labs(title = "Frecuencia de Stress Level",
       x = "Nivel de estrés", y = "Frecuencia") +
  theme_minimal()

Interpretación: permite identificar cuáles niveles de estrés se presentan con mayor frecuencia.

ggplot(datos, aes(x = Stress.Level)) +
  geom_histogram(bins = 8, fill = "skyblue", color = "black") +
  labs(title = "Distribución de Stress Level",
       x = "Nivel de estrés", y = "Frecuencia") +
  theme_minimal()

Interpretación: resume la forma general de la distribución.

ggplot(datos, aes(y = Stress.Level)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Stress Level", y = "Nivel de estrés") +
  theme_minimal()

Interpretación: sintetiza variabilidad y valores atípicos.

ggplot(datos, aes(x = Gender, y = Stress.Level, fill = Gender)) +
  geom_boxplot() +
  labs(title = "Stress Level por Gender",
       x = "Género", y = "Nivel de estrés") +
  theme_minimal()

Interpretación: permite identificar si el estrés tiende a diferir según género.

ggplot(datos, aes(x = Sleep.Duration, y = Stress.Level)) +
  geom_point(color = "red") +
  labs(title = "Sleep Duration vs Stress Level",
       x = "Horas de sueño", y = "Nivel de estrés") +
  theme_minimal()

Interpretación: se espera una tendencia inversa, donde menor tiempo de sueño se asocie con mayor estrés.

4.9 9. BMI Category

La variable BMI Category es categórica nominal. Se recomienda trabajar con barras, pastel, barras apiladas y gráficos de asociación.

ggplot(datos, aes(x = BMI.Category)) +
  geom_bar(fill = "steelblue", color = "black") +
  labs(title = "Frecuencia de BMI Category",
       x = "Categoría BMI", y = "Frecuencia") +
  theme_minimal()

Interpretación: permite identificar la categoría corporal predominante en la muestra.

tabla_bmi <- preparar_pastel(datos$BMI.Category)

ggplot(tabla_bmi, aes(x = "", y = Proporcion, fill = Categoria)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar(theta = "y") +
  geom_text(aes(label = Etiqueta),
            position = position_stack(vjust = 0.5), size = 4) +
  labs(title = "Proporción de BMI Category", fill = "BMI") +
  theme_void()

Interpretación: resume la distribución relativa de las categorías de IMC y presenta el porcentaje directamente en cada sector.

ggplot(datos, aes(x = BMI.Category, fill = Gender)) +
  geom_bar(position = "fill") +
  labs(title = "Proporción de Gender por BMI Category",
       x = "Categoría BMI", y = "Proporción", fill = "Género") +
  theme_minimal()

Interpretación: facilita la comparación proporcional de la composición por género dentro de cada categoría corporal.

ggplot(datos, aes(x = BMI.Category, fill = Sleep.Disorder)) +
  geom_bar(position = "fill") +
  labs(title = "Proporción de Sleep Disorder por BMI Category",
       x = "Categoría BMI", y = "Proporción", fill = "Sleep Disorder") +
  theme_minimal()

Interpretación: permite explorar la composición proporcional de trastornos del sueño dentro de cada categoría corporal.

4.10 10. Blood Pressure, Systolic y Diastolic

La variable original Blood Pressure es una cadena de texto y por ello no debe analizarse directamente como cuantitativa. Las visualizaciones recomendadas se realizan sobre las variables derivadas Systolic y Diastolic.

ggplot(datos, aes(x = Systolic)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Distribución de Systolic",
       x = "Presión sistólica", y = "Frecuencia") +
  theme_minimal()

Interpretación: describe la distribución de la presión arterial sistólica.

ggplot(datos, aes(x = Diastolic)) +
  geom_histogram(bins = 10, fill = "orange", color = "black") +
  labs(title = "Distribución de Diastolic",
       x = "Presión diastólica", y = "Frecuencia") +
  theme_minimal()

Interpretación: describe la distribución de la presión arterial diastólica.

ggplot(datos, aes(x = Systolic, y = Diastolic)) +
  geom_point(color = "blue") +
  labs(title = "Relación entre Systolic y Diastolic",
       x = "Presión sistólica", y = "Presión diastólica") +
  theme_minimal()

Interpretación: permite examinar la relación fisiológica entre ambas medidas de presión arterial.

ggplot(datos, aes(x = Gender, y = Systolic, fill = Gender)) +
  geom_boxplot() +
  labs(title = "Systolic por Gender",
       x = "Género", y = "Presión sistólica") +
  theme_minimal()

Interpretación: facilita la comparación de la presión sistólica entre géneros.

4.11 11. Heart Rate

La variable Heart Rate es cuantitativa discreta y resulta apropiada para histogramas, boxplots, densidades y gráficos de dispersión.

ggplot(datos, aes(x = Heart.Rate)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Distribución de Heart Rate",
       x = "Frecuencia cardíaca", y = "Frecuencia") +
  theme_minimal()

Interpretación: muestra la concentración de frecuencias cardíacas observadas.

ggplot(datos, aes(y = Heart.Rate)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Heart Rate", y = "Frecuencia cardíaca") +
  theme_minimal()

Interpretación: resume el centro, la dispersión y los posibles valores atípicos.

ggplot(datos, aes(x = Heart.Rate)) +
  geom_density(fill = "orange", alpha = 0.4) +
  labs(title = "Densidad de Heart Rate",
       x = "Frecuencia cardíaca", y = "Densidad") +
  theme_minimal()

Interpretación: permite examinar la forma de la distribución.

ggplot(datos, aes(x = Stress.Level, y = Heart.Rate)) +
  geom_point(color = "red") +
  labs(title = "Stress Level vs Heart Rate",
       x = "Nivel de estrés", y = "Frecuencia cardíaca") +
  theme_minimal()

Interpretación: ayuda a evaluar la posible asociación positiva entre estrés y frecuencia cardíaca.

4.12 12. Daily Steps

La variable Daily Steps es cuantitativa discreta y representa un indicador de actividad cotidiana.

ggplot(datos, aes(x = Daily.Steps)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Distribución de Daily Steps",
       x = "Pasos diarios", y = "Frecuencia") +
  theme_minimal()

Interpretación: permite identificar el rango habitual de pasos realizados por los participantes.

ggplot(datos, aes(y = Daily.Steps)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Daily Steps", y = "Pasos diarios") +
  theme_minimal()

Interpretación: resume la dispersión y la presencia de individuos particularmente activos o sedentarios.

ggplot(datos, aes(x = Daily.Steps)) +
  geom_density(fill = "orange", alpha = 0.4) +
  labs(title = "Densidad de Daily Steps",
       x = "Pasos diarios", y = "Densidad") +
  theme_minimal()

Interpretación: facilita la lectura de la forma de la distribución.

ggplot(datos, aes(x = Physical.Activity.Level, y = Daily.Steps)) +
  geom_point(color = "blue") +
  labs(title = "Physical Activity Level vs Daily Steps",
       x = "Nivel de actividad física", y = "Pasos diarios") +
  theme_minimal()

Interpretación: se espera una relación positiva entre ambas variables, dado que ambas miden actividad física desde perspectivas complementarias.

4.13 13. Sleep Disorder

La variable Sleep Disorder es categórica nominal. Sus representaciones más útiles son barras, pastel y análisis cruzados con otras variables categóricas.

ggplot(datos, aes(x = Sleep.Disorder)) +
  geom_bar(fill = "steelblue", color = "black") +
  labs(title = "Frecuencia de Sleep Disorder",
       x = "Trastorno del sueño", y = "Frecuencia") +
  theme_minimal()

Interpretación: permite establecer la frecuencia de ausencia de trastorno, insomnio y apnea del sueño.

tabla_sd <- preparar_pastel(datos$Sleep.Disorder)

ggplot(tabla_sd, aes(x = "", y = Proporcion, fill = Categoria)) +
  geom_bar(stat = "identity", width = 1) +
  coord_polar(theta = "y") +
  geom_text(aes(label = Etiqueta),
            position = position_stack(vjust = 0.5), size = 4) +
  labs(title = "Proporción de Sleep Disorder", fill = "Sleep Disorder") +
  theme_void()

Interpretación: resume la participación relativa de cada categoría de trastorno del sueño e incluye el porcentaje en cada sector.

ggplot(datos, aes(x = Gender, fill = Sleep.Disorder)) +
  geom_bar(position = "fill") +
  labs(title = "Proporción de Sleep Disorder por Gender",
       x = "Género", y = "Proporción", fill = "Sleep Disorder") +
  theme_minimal()

Interpretación: permite explorar cómo varía la composición proporcional de trastornos del sueño entre hombres y mujeres.

ggplot(datos, aes(x = BMI.Category, fill = Sleep.Disorder)) +
  geom_bar(position = "fill") +
  labs(title = "Proporción de Sleep Disorder por BMI Category",
       x = "Categoría BMI", y = "Proporción", fill = "Sleep Disorder") +
  theme_minimal()

Interpretación: ayuda a estudiar la composición proporcional de trastornos del sueño según condición corporal.

5 Sección aparte: análisis de normalidad

La evaluación de normalidad se realiza sobre las variables cuantitativas que, por su naturaleza, podrían ser consideradas en técnicas paramétricas. Debe tenerse presente que la prueba de Shapiro-Wilk es sensible al tamaño muestral; por ello se complementa con la inspección visual del gráfico QQ.

5.1 Variables seleccionadas para normalidad

Las variables consideradas en esta sección son: Age, Sleep Duration, Quality of Sleep, Physical Activity Level, Stress Level, Heart Rate, Daily Steps, Systolic y Diastolic. La variable Person ID no se evalúa por su carácter identificador y las variables categóricas quedan excluidas.

variables_normalidad <- c(
  "Age", "Sleep.Duration", "Quality.of.Sleep", "Physical.Activity.Level",
  "Stress.Level", "Heart.Rate", "Daily.Steps", "Systolic", "Diastolic"
)

resultados_shapiro <- data.frame(
  Variable = character(),
  W = numeric(),
  p_value = numeric(),
  stringsAsFactors = FALSE
)

for (v in variables_normalidad) {
  prueba <- shapiro.test(datos[[v]])
  resultados_shapiro <- rbind(
    resultados_shapiro,
    data.frame(Variable = v, W = as.numeric(prueba$statistic), p_value = prueba$p.value)
  )
}

resultados_shapiro
##                  Variable         W      p_value
## 1                     Age 0.9580017 7.416837e-09
## 2          Sleep.Duration 0.9357678 1.267828e-11
## 3        Quality.of.Sleep 0.8938632 1.881529e-15
## 4 Physical.Activity.Level 0.8994274 5.176356e-15
## 5            Stress.Level 0.8908905 1.112608e-15
## 6              Heart.Rate 0.8825502 2.684952e-16
## 7             Daily.Steps 0.9368167 1.653179e-11
## 8                Systolic 0.9246805 9.010577e-13
## 9               Diastolic 0.8940533 1.946526e-15

Interpretación general: si el valor-p es menor que 0.05, se rechaza la hipótesis de normalidad. Sin embargo, esta conclusión debe complementarse con la inspección del gráfico QQ y con el contexto del modelado posterior.

5.2 QQ plots

par(mfrow = c(3, 3))
for (v in variables_normalidad) {
  qqnorm(datos[[v]], main = paste("QQ Plot -", v))
  qqline(datos[[v]], col = 2, lwd = 2)
}

par(mfrow = c(1, 1))

Interpretación general: cuando los puntos siguen aproximadamente la línea de referencia, la distribución se aproxima a la normalidad. Desviaciones sistemáticas en los extremos o curvaturas marcadas sugieren asimetría, colas pesadas o ausencia de normalidad.

5.3 Comentario metodológico sobre la normalidad

En esta base, varias variables son discretas u ordinales, por lo que la normalidad perfecta no necesariamente debe esperarse. No obstante, la evaluación sigue siendo útil para decidir entre enfoques paramétricos y no paramétricos, así como para revisar supuestos de residuos en modelos de regresión.

6 Sección aparte: modelado con variables correspondientes

En esta sección se proponen modelos coherentes con la estructura de la base de datos. Se excluye Person ID del modelado por su función de identificador.

6.1 Modelo 1. Regresión lineal para Quality of Sleep

Se propone un modelo de regresión lineal múltiple donde la variable respuesta es Quality of Sleep. Esta elección es razonable porque dicha variable resume el resultado principal de interés y puede explicarse a partir de duración del sueño, estrés, actividad física, frecuencia cardíaca, edad, género y categoría BMI.

modelo_quality <- lm(
  Quality.of.Sleep ~ Sleep.Duration + Stress.Level + Physical.Activity.Level +
    Heart.Rate + Daily.Steps + Age + Gender + BMI.Category,
  data = datos
)

summary(modelo_quality)
## 
## Call:
## lm(formula = Quality.of.Sleep ~ Sleep.Duration + Stress.Level + 
##     Physical.Activity.Level + Heart.Rate + Daily.Steps + Age + 
##     Gender + BMI.Category, data = datos)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.02977 -0.15531 -0.05828  0.18686  1.02552 
## 
## Coefficients:
##                           Estimate Std. Error t value Pr(>|t|)    
## (Intercept)              6.1431902  0.6401619   9.596  < 2e-16 ***
## Sleep.Duration           0.1714409  0.0480921   3.565 0.000413 ***
## Stress.Level            -0.4326496  0.0267523 -16.172  < 2e-16 ***
## Physical.Activity.Level  0.0027118  0.0017153   1.581 0.114755    
## Heart.Rate              -0.0028352  0.0093115  -0.304 0.760935    
## Daily.Steps              0.0000547  0.0000220   2.486 0.013352 *  
## Age                      0.0510263  0.0032827  15.544  < 2e-16 ***
## GenderMale               0.2342816  0.0463897   5.050 6.99e-07 ***
## BMI.CategoryObese       -0.7135524  0.1618490  -4.409 1.37e-05 ***
## BMI.CategoryOverweight  -0.7820835  0.0555258 -14.085  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2907 on 364 degrees of freedom
## Multiple R-squared:  0.9424, Adjusted R-squared:  0.941 
## F-statistic: 662.2 on 9 and 364 DF,  p-value: < 2.2e-16

Interpretación sugerida: los coeficientes indican el cambio esperado en la calidad del sueño ante una variación unitaria en cada predictor, manteniendo constantes las demás variables. Resultan especialmente relevantes los signos y significancia de Sleep.Duration, Stress.Level y Physical.Activity.Level.

6.1.1 Diagnóstico de residuos del modelo lineal

par(mfrow = c(2, 2))
plot(modelo_quality)

par(mfrow = c(1, 1))

Interpretación: estos gráficos permiten evaluar linealidad, homocedasticidad, normalidad aproximada de residuos y observaciones influyentes.

6.2 Modelo 2. Regresión lineal para Heart Rate

En este segundo modelo, Heart Rate se toma como variable respuesta por su importancia fisiológica. Se propone explicarla mediante estrés, duración del sueño, actividad física, edad, presión sistólica y categoría BMI.

modelo_hr <- lm(
  Heart.Rate ~ Stress.Level + Sleep.Duration + Physical.Activity.Level +
    Age + Systolic + BMI.Category,
  data = datos
)

summary(modelo_hr)
## 
## Call:
## lm(formula = Heart.Rate ~ Stress.Level + Sleep.Duration + Physical.Activity.Level + 
##     Age + Systolic + BMI.Category, data = datos)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -5.4840 -0.6615 -0.0760  0.5357  9.2881 
## 
## Coefficients:
##                          Estimate Std. Error t value Pr(>|t|)    
## (Intercept)             57.718346   3.348700  17.236  < 2e-16 ***
## Stress.Level             1.735190   0.103300  16.798  < 2e-16 ***
## Sleep.Duration           0.742469   0.272882   2.721  0.00682 ** 
## Physical.Activity.Level  0.030933   0.005326   5.808 1.37e-08 ***
## Age                     -0.003867   0.021274  -0.182  0.85585    
## Systolic                -0.038667   0.023556  -1.641  0.10156    
## BMI.CategoryObese       15.351578   0.706272  21.736  < 2e-16 ***
## BMI.CategoryOverweight   1.771813   0.362337   4.890 1.51e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.871 on 366 degrees of freedom
## Multiple R-squared:  0.7991, Adjusted R-squared:  0.7953 
## F-statistic:   208 on 7 and 366 DF,  p-value: < 2.2e-16

Interpretación sugerida: este modelo permite establecer cuáles variables se asocian con incrementos o reducciones en la frecuencia cardíaca.

6.2.1 Diagnóstico de residuos del modelo de Heart Rate

par(mfrow = c(2, 2))
plot(modelo_hr)

par(mfrow = c(1, 1))

Interpretación: la validez del modelo depende en buena medida de que los residuos no presenten patrones sistemáticos severos.

6.3 Modelo 3. Regresión logística binaria para presencia de trastorno del sueño

Dado que Sleep Disorder es categórica con múltiples clases, se construye una variable binaria auxiliar denominada Sleep.Disorder.Binary, donde 0 representa ausencia de trastorno y 1 representa presencia de algún trastorno del sueño. Esto permite emplear una regresión logística binaria.

datos$Sleep.Disorder.Binary.Num <- ifelse(datos$Sleep.Disorder == "No Disorder", 0, 1)

modelo_logistico <- glm(
  Sleep.Disorder.Binary.Num ~ Age + Gender + Sleep.Duration + Stress.Level +
    Quality.of.Sleep + BMI.Category + Heart.Rate + Systolic,
  data = datos,
  family = binomial
)

summary(modelo_logistico)
## 
## Call:
## glm(formula = Sleep.Disorder.Binary.Num ~ Age + Gender + Sleep.Duration + 
##     Stress.Level + Quality.of.Sleep + BMI.Category + Heart.Rate + 
##     Systolic, family = binomial, data = datos)
## 
## Coefficients:
##                          Estimate Std. Error z value Pr(>|z|)
## (Intercept)             2.657e+01  8.231e+05       0        1
## Age                    -1.025e-07  5.715e+03       0        1
## GenderMale             -2.555e-07  5.887e+04       0        1
## Sleep.Duration          1.697e-06  5.912e+04       0        1
## Stress.Level           -6.353e-08  3.853e+04       0        1
## Quality.of.Sleep        6.550e-07  5.895e+04       0        1
## BMI.CategoryObese      -4.202e-06  2.076e+05       0        1
## BMI.CategoryOverweight -1.505e-06  8.451e+04       0        1
## Heart.Rate              9.207e-08  9.986e+03       0        1
## Systolic                7.855e-08  4.444e+03       0        1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 0.0000e+00  on 373  degrees of freedom
## Residual deviance: 2.1698e-09  on 364  degrees of freedom
## AIC: 20
## 
## Number of Fisher Scoring iterations: 25

Interpretación sugerida: los coeficientes positivos aumentan el logaritmo de la razón de probabilidades de presentar trastorno del sueño, mientras que los coeficientes negativos lo reducen.

6.3.1 Odds ratios del modelo logístico

exp(coef(modelo_logistico))
##            (Intercept)                    Age             GenderMale 
##           3.447339e+11           9.999999e-01           9.999997e-01 
##         Sleep.Duration           Stress.Level       Quality.of.Sleep 
##           1.000002e+00           9.999999e-01           1.000001e+00 
##      BMI.CategoryObese BMI.CategoryOverweight             Heart.Rate 
##           9.999958e-01           9.999985e-01           1.000000e+00 
##               Systolic 
##           1.000000e+00

Interpretación: los valores mayores que 1 indican aumento en la razón de probabilidades, mientras que los menores que 1 sugieren un efecto protector o reductor sobre la probabilidad de presentar trastorno del sueño.

6.4 Matriz de correlación para apoyo al modelado

Antes del modelado es conveniente revisar las relaciones lineales entre variables cuantitativas.

vars_cor <- datos[, c(
  "Age", "Sleep.Duration", "Quality.of.Sleep", "Physical.Activity.Level",
  "Stress.Level", "Heart.Rate", "Daily.Steps", "Systolic", "Diastolic"
)]

mat_cor <- cor(vars_cor, use = "complete.obs")
mat_cor
##                                Age Sleep.Duration Quality.of.Sleep
## Age                      1.0000000     0.34470936       0.47373388
## Sleep.Duration           0.3447094     1.00000000       0.88321300
## Quality.of.Sleep         0.4737339     0.88321300       1.00000000
## Physical.Activity.Level  0.1789927     0.21236031       0.19289645
## Stress.Level            -0.4223445    -0.81102303      -0.89875203
## Heart.Rate              -0.2256062    -0.51645489      -0.65986473
## Daily.Steps              0.0579734    -0.03953254       0.01679141
## Systolic                 0.6058784    -0.18040628      -0.12163200
## Diastolic                0.5938389    -0.16656987      -0.11015093
##                         Physical.Activity.Level Stress.Level  Heart.Rate
## Age                                  0.17899272  -0.42234448 -0.22560619
## Sleep.Duration                       0.21236031  -0.81102303 -0.51645489
## Quality.of.Sleep                     0.19289645  -0.89875203 -0.65986473
## Physical.Activity.Level              1.00000000  -0.03413446  0.13697098
## Stress.Level                        -0.03413446   1.00000000  0.67002646
## Heart.Rate                           0.13697098   0.67002646  1.00000000
## Daily.Steps                          0.77272305   0.18682895 -0.03030858
## Systolic                             0.26541597   0.10281816  0.29414292
## Diastolic                            0.38265068   0.09181104  0.27109222
##                         Daily.Steps   Systolic   Diastolic
## Age                      0.05797340  0.6058784  0.59383892
## Sleep.Duration          -0.03953254 -0.1804063 -0.16656987
## Quality.of.Sleep         0.01679141 -0.1216320 -0.11015093
## Physical.Activity.Level  0.77272305  0.2654160  0.38265068
## Stress.Level             0.18682895  0.1028182  0.09181104
## Heart.Rate              -0.03030858  0.2941429  0.27109222
## Daily.Steps              1.00000000  0.1033422  0.24198597
## Systolic                 0.10334222  1.0000000  0.97288499
## Diastolic                0.24198597  0.9728850  1.00000000
cor_df <- as.data.frame(as.table(mat_cor))
colnames(cor_df) <- c("Var1", "Var2", "Correlacion")

ggplot(cor_df, aes(x = Var1, y = Var2, fill = Correlacion)) +
  geom_tile(color = "white") +
  labs(title = "Mapa de calor de correlaciones",
       x = "", y = "", fill = "Correlación") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Interpretación: este mapa permite identificar asociaciones lineales altas que pueden ser relevantes para la interpretación o para la detección de colinealidad entre predictores.

7 Conclusiones

La revisión de variables evidencia que la base combina variables identificadoras, categóricas, cuantitativas y una variable compuesta que requiere transformación previa. Las visualizaciones recomendadas permiten estudiar adecuadamente la distribución, la dispersión y las asociaciones bivariadas según la naturaleza de cada variable. La sección de normalidad constituye un insumo para decidir la conveniencia de ciertos métodos paramétricos y para evaluar supuestos en los modelos. Finalmente, la sección de modelado muestra rutas analíticas coherentes: una regresión lineal para explicar la calidad del sueño, otra para la frecuencia cardíaca y una regresión logística para analizar la presencia de trastornos del sueño.

Desde una perspectiva aplicada, las variables más relevantes de la base son Sleep Duration, Quality of Sleep, Stress Level, Heart Rate, BMI Category y las medidas de presión arterial. Estas variables articulan de forma consistente el análisis descriptivo, la evaluación de supuestos y el modelado estadístico.