1 1. Introducción

El presente documento desarrolla un análisis integral de la base de datos Sleep_health_and_lifestyle_dataset.csv. En primer lugar, se realiza la revisión de las variables y los ajustes previos necesarios para garantizar consistencia analítica. Posteriormente, se presentan visualizaciones univariadas y bivariadas, incluyendo comparaciones entre variables categóricas y cuantitativas. En una sección independiente se incorpora el análisis de normalidad mediante la prueba de Shapiro-Wilk y gráficos QQ para las variables cuantitativas. Finalmente, se incluyen ejemplos de modelado estadístico con variables seleccionadas de acuerdo con su naturaleza y pertinencia analítica.

2 2. Carga y preparación de los datos

datos <- read.csv("Sleep_health_and_lifestyle_dataset.csv", stringsAsFactors = FALSE)

dim(datos)
## [1] 374  13
names(datos)
##  [1] "Person.ID"               "Gender"                 
##  [3] "Age"                     "Occupation"             
##  [5] "Sleep.Duration"          "Quality.of.Sleep"       
##  [7] "Physical.Activity.Level" "Stress.Level"           
##  [9] "BMI.Category"            "Blood.Pressure"         
## [11] "Heart.Rate"              "Daily.Steps"            
## [13] "Sleep.Disorder"
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" ...
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 2.1 Ajustes previos

# Copia de trabajo
datos2 <- datos

# Unificar categorías en BMI
datos2$BMI.Category[datos2$BMI.Category == "Normal Weight"] <- "Normal"

# Reemplazar NA en Sleep Disorder
datos2$Sleep.Disorder[is.na(datos2$Sleep.Disorder) | datos2$Sleep.Disorder == ""] <- "No Disorder"

# Convertir variables categóricas a factor
datos2$Gender <- as.factor(datos2$Gender)
datos2$Occupation <- as.factor(datos2$Occupation)
datos2$BMI.Category <- as.factor(datos2$BMI.Category)
datos2$Sleep.Disorder <- as.factor(datos2$Sleep.Disorder)

# Separar Blood Pressure en Systolic y Diastolic
bp_split <- strsplit(as.character(datos2$Blood.Pressure), "/")
datos2$Systolic <- as.numeric(sapply(bp_split, `[`, 1))
datos2$Diastolic <- as.numeric(sapply(bp_split, `[`, 2))

str(datos2)
## 'data.frame':    374 obs. of  15 variables:
##  $ Person.ID              : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ Gender                 : Factor w/ 2 levels "Female","Male": 2 2 2 2 2 2 2 2 2 2 ...
##  $ Age                    : int  27 28 28 28 28 28 29 29 29 29 ...
##  $ Occupation             : Factor w/ 11 levels "Accountant","Doctor",..: 10 2 2 7 7 10 11 2 2 2 ...
##  $ 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 ...

3 3. Revisión de las variables

3.1 3.1 Tabla de revisión

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"
  ),
  Tipo = c(
    "Identificador", "Categórica nominal", "Cuantitativa discreta",
    "Categórica nominal", "Cuantitativa continua",
    "Cuantitativa discreta/ordinal", "Cuantitativa discreta",
    "Cuantitativa discreta/ordinal", "Categórica nominal",
    "Compuesta en texto", "Cuantitativa discreta",
    "Cuantitativa discreta", "Categórica nominal",
    "Cuantitativa discreta", "Cuantitativa discreta"
  ),
  Uso_analitico = c(
    "No se recomienda para modelado ni visualización sustantiva",
    "Comparación de grupos",
    "Distribución y asociación con salud/sueño",
    "Comparación de grupos",
    "Variable clave de sueño",
    "Indicador de calidad percibida del sueño",
    "Indicador de estilo de vida",
    "Indicador de estrés",
    "Comparación de grupos y salud",
    "Debe separarse en sistólica y diastólica",
    "Indicador cardiovascular",
    "Indicador de actividad diaria",
    "Variable respuesta categórica útil para clasificación",
    "Indicador cardiovascular",
    "Indicador cardiovascular"
  ),
  stringsAsFactors = FALSE
)
knitr::kable(revision_variables, caption = "Revisión general de las variables")
Revisión general de las variables
Variable Tipo Uso_analitico
Person.ID Identificador No se recomienda para modelado ni visualización sustantiva
Gender Categórica nominal Comparación de grupos
Age Cuantitativa discreta Distribución y asociación con salud/sueño
Occupation Categórica nominal Comparación de grupos
Sleep.Duration Cuantitativa continua Variable clave de sueño
Quality.of.Sleep Cuantitativa discreta/ordinal Indicador de calidad percibida del sueño
Physical.Activity.Level Cuantitativa discreta Indicador de estilo de vida
Stress.Level Cuantitativa discreta/ordinal Indicador de estrés
BMI.Category Categórica nominal Comparación de grupos y salud
Blood.Pressure Compuesta en texto Debe separarse en sistólica y diastólica
Heart.Rate Cuantitativa discreta Indicador cardiovascular
Daily.Steps Cuantitativa discreta Indicador de actividad diaria
Sleep.Disorder Categórica nominal Variable respuesta categórica útil para clasificación
Systolic Cuantitativa discreta Indicador cardiovascular
Diastolic Cuantitativa discreta Indicador cardiovascular

3.2 3.2 Interpretación general

La base combina variables demográficas, ocupacionales, fisiológicas y relacionadas con la calidad del sueño. Desde el punto de vista analítico, la variable Person.ID solo cumple una función de identificación, por lo que no se considera en los análisis sustantivos. La variable Blood.Pressure requiere una transformación previa para separar presión sistólica y diastólica, mientras que BMI.Category y Sleep.Disorder exigen ajustes de consistencia y tratamiento de valores faltantes para mejorar la interpretación de los resultados.

4 4. Funciones auxiliares para visualización

grafico_pastel <- function(data, var, titulo, leyenda){
  tabla <- table(data[[var]])
  df_tabla <- as.data.frame(tabla)
  df_tabla$prop <- df_tabla$Freq / sum(df_tabla$Freq)
  df_tabla$label <- paste0(round(df_tabla$prop * 100, 1), "%")

  ggplot(df_tabla, aes(x = "", y = prop, fill = Var1)) +
    geom_bar(stat = "identity", width = 1, color = "white") +
    coord_polar(theta = "y") +
    geom_text(aes(label = label),
              position = position_stack(vjust = 0.5),
              size = 4) +
    labs(title = titulo, fill = leyenda) +
    theme_void()
}

barras_proporcion <- function(data, xvar, fillvar, titulo, xlab, filllab){
  ggplot(data, aes_string(x = xvar, fill = fillvar)) +
    geom_bar(position = "fill") +
    labs(title = titulo, x = xlab, y = "Proporción", fill = filllab)
}

hist_por_grupo <- function(data, xvar, groupvar, titulo, xlab, legenda){
  ggplot(data, aes_string(x = xvar, fill = groupvar)) +
    geom_histogram(alpha = 0.5, position = "identity", bins = 10) +
    labs(title = titulo, x = xlab, y = "Frecuencia", fill = legenda)
}

densidad_por_grupo <- function(data, xvar, groupvar, titulo, xlab, legenda){
  ggplot(data, aes_string(x = xvar, color = groupvar, fill = groupvar)) +
    geom_density(alpha = 0.2) +
    labs(title = titulo, x = xlab, y = "Densidad", color = legenda, fill = legenda)
}

boxplot_por_grupo <- function(data, xvar, yvar, titulo, xlab, ylab){
  ggplot(data, aes_string(x = xvar, y = yvar, fill = xvar)) +
    geom_boxplot() +
    labs(title = titulo, x = xlab, y = ylab)
}

scatter_tendencia <- function(data, xvar, yvar, titulo, xlab, ylab){
  ggplot(data, aes_string(x = xvar, y = yvar)) +
    geom_point(alpha = 0.7) +
    geom_smooth(method = "lm", se = TRUE) +
    labs(title = titulo, x = xlab, y = ylab)
}

5 5. Visualización univariada

5.1 5.1 Variables categóricas

5.1.1 Gender

ggplot(datos2, aes(x = Gender)) +
  geom_bar(fill = "steelblue", color = "black") +
  labs(title = "Distribución de Gender", x = "Gender", y = "Frecuencia")

Interpretación: la variable Gender permite identificar el balance de la muestra entre hombres y mujeres, lo cual resulta importante para comparaciones posteriores por grupos.

grafico_pastel(datos2, "Gender", "Proporción de Gender", "Gender")

Interpretación: el gráfico de pastel resume la distribución relativa de la variable y expresa el porcentaje que representa cada categoría dentro de la muestra total.

5.1.2 Occupation

ggplot(datos2, aes(x = reorder(Occupation, Occupation, function(x) -length(x)))) +
  geom_bar(fill = "steelblue", color = "black") +
  coord_flip() +
  labs(title = "Frecuencia de Occupation", x = "Occupation", y = "Frecuencia")

Interpretación: la visualización permite comparar cuáles ocupaciones tienen mayor o menor representación en la base.

grafico_pastel(datos2, "Occupation", "Proporción de Occupation", "Occupation")

Interpretación: el gráfico de pastel presenta la participación relativa de cada ocupación dentro del conjunto de observaciones.

5.1.3 BMI Category

ggplot(datos2, aes(x = BMI.Category)) +
  geom_bar(fill = "steelblue", color = "black") +
  labs(title = "Frecuencia de BMI Category", x = "BMI Category", y = "Frecuencia")

Interpretación: permite identificar la categoría de IMC predominante y observar la estructura general del estado corporal de la muestra.

grafico_pastel(datos2, "BMI.Category", "Proporción de BMI Category", "BMI Category")

Interpretación: el porcentaje por categoría facilita la comprensión del peso relativo de cada grupo de IMC.

5.1.4 Sleep Disorder

ggplot(datos2, aes(x = Sleep.Disorder)) +
  geom_bar(fill = "steelblue", color = "black") +
  labs(title = "Frecuencia de Sleep Disorder", x = "Sleep Disorder", y = "Frecuencia")

Interpretación: permite observar la presencia relativa de personas sin trastorno y de quienes presentan insomnio u otros trastornos del sueño.

grafico_pastel(datos2, "Sleep.Disorder", "Proporción de Sleep Disorder", "Sleep Disorder")

Interpretación: el porcentaje por categoría facilita una lectura rápida de la prevalencia de cada trastorno.

5.2 5.2 Variables cuantitativas

cuantitativas <- c(
  "Age", "Sleep.Duration", "Quality.of.Sleep", "Physical.Activity.Level",
  "Stress.Level", "Heart.Rate", "Daily.Steps", "Systolic", "Diastolic"
)
cuantitativas
## [1] "Age"                     "Sleep.Duration"         
## [3] "Quality.of.Sleep"        "Physical.Activity.Level"
## [5] "Stress.Level"            "Heart.Rate"             
## [7] "Daily.Steps"             "Systolic"               
## [9] "Diastolic"

5.2.1 Age

ggplot(datos2, aes(x = Age)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Histograma de Age", x = "Age", y = "Frecuencia")

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

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

Interpretación: estas visualizaciones permiten examinar la distribución, dispersión y forma general de la edad en la muestra.

5.2.2 Sleep Duration

ggplot(datos2, aes(x = Sleep.Duration)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Histograma de Sleep Duration", x = "Sleep Duration", y = "Frecuencia")

ggplot(datos2, aes(y = Sleep.Duration)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Sleep Duration", y = "Sleep Duration")

ggplot(datos2, aes(x = Sleep.Duration)) +
  geom_density(fill = "orange", alpha = 0.4) +
  labs(title = "Densidad de Sleep Duration", x = "Sleep Duration", y = "Densidad")

Interpretación: el conjunto de gráficos permite identificar concentración de horas de sueño, dispersión y posibles asimetrías.

5.2.3 Quality of Sleep

ggplot(datos2, aes(x = Quality.of.Sleep)) +
  geom_histogram(bins = 8, fill = "skyblue", color = "black") +
  labs(title = "Histograma de Quality of Sleep", x = "Quality of Sleep", y = "Frecuencia")

ggplot(datos2, aes(y = Quality.of.Sleep)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Quality of Sleep", y = "Quality of Sleep")

ggplot(datos2, aes(x = Quality.of.Sleep)) +
  geom_density(fill = "orange", alpha = 0.4) +
  labs(title = "Densidad de Quality of Sleep", x = "Quality of Sleep", y = "Densidad")

Interpretación: estas gráficas muestran cómo se distribuye la percepción de la calidad del sueño y si existen valores extremos.

5.2.4 Physical Activity Level

ggplot(datos2, aes(x = Physical.Activity.Level)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Histograma de Physical Activity Level", x = "Physical Activity Level", y = "Frecuencia")

ggplot(datos2, aes(y = Physical.Activity.Level)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Physical Activity Level", y = "Physical Activity Level")

ggplot(datos2, aes(x = Physical.Activity.Level)) +
  geom_density(fill = "orange", alpha = 0.4) +
  labs(title = "Densidad de Physical Activity Level", x = "Physical Activity Level", y = "Densidad")

Interpretación: el análisis gráfico permite valorar la actividad física diaria y su dispersión entre individuos.

5.2.5 Stress Level

ggplot(datos2, aes(x = Stress.Level)) +
  geom_histogram(bins = 8, fill = "skyblue", color = "black") +
  labs(title = "Histograma de Stress Level", x = "Stress Level", y = "Frecuencia")

ggplot(datos2, aes(y = Stress.Level)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Stress Level", y = "Stress Level")

ggplot(datos2, aes(x = Stress.Level)) +
  geom_density(fill = "orange", alpha = 0.4) +
  labs(title = "Densidad de Stress Level", x = "Stress Level", y = "Densidad")

Interpretación: estas gráficas permiten caracterizar los niveles de estrés y revisar si predominan niveles bajos, medios o altos.

5.2.6 Heart Rate

ggplot(datos2, aes(x = Heart.Rate)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Histograma de Heart Rate", x = "Heart Rate", y = "Frecuencia")

ggplot(datos2, aes(y = Heart.Rate)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Heart Rate", y = "Heart Rate")

ggplot(datos2, aes(x = Heart.Rate)) +
  geom_density(fill = "orange", alpha = 0.4) +
  labs(title = "Densidad de Heart Rate", x = "Heart Rate", y = "Densidad")

Interpretación: los gráficos permiten revisar la frecuencia cardíaca típica de la muestra y posibles observaciones extremas.

5.2.7 Daily Steps

ggplot(datos2, aes(x = Daily.Steps)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Histograma de Daily Steps", x = "Daily Steps", y = "Frecuencia")

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

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

Interpretación: estas visualizaciones permiten examinar el comportamiento del número de pasos diarios y su dispersión.

5.2.8 Systolic y Diastolic

ggplot(datos2, aes(x = Systolic)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Histograma de Systolic", x = "Systolic", y = "Frecuencia")

ggplot(datos2, aes(y = Systolic)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Systolic", y = "Systolic")

ggplot(datos2, aes(x = Systolic)) +
  geom_density(fill = "orange", alpha = 0.4) +
  labs(title = "Densidad de Systolic", x = "Systolic", y = "Densidad")

ggplot(datos2, aes(x = Diastolic)) +
  geom_histogram(bins = 10, fill = "skyblue", color = "black") +
  labs(title = "Histograma de Diastolic", x = "Diastolic", y = "Frecuencia")

ggplot(datos2, aes(y = Diastolic)) +
  geom_boxplot(fill = "lightgreen", color = "black") +
  labs(title = "Boxplot de Diastolic", y = "Diastolic")

ggplot(datos2, aes(x = Diastolic)) +
  geom_density(fill = "orange", alpha = 0.4) +
  labs(title = "Densidad de Diastolic", x = "Diastolic", y = "Densidad")

Interpretación: la separación de la presión arterial en componentes sistólica y diastólica permite revisar cada distribución por separado.

6 6. Visualización bivariada

6.1 6.1 Categórica vs categórica

6.1.1 Gender vs Sleep Disorder

barras_proporcion(
  datos2, "Gender", "Sleep.Disorder",
  "Proporción de Sleep Disorder por Gender",
  "Gender", "Sleep Disorder"
)

mosaicplot(table(datos2$Gender, datos2$Sleep.Disorder),
           main = "Gender vs Sleep Disorder",
           color = TRUE)

Interpretación: estas visualizaciones permiten comparar la composición porcentual de los trastornos del sueño dentro de cada género.

6.1.2 BMI Category vs Sleep Disorder

barras_proporcion(
  datos2, "BMI.Category", "Sleep.Disorder",
  "Proporción de Sleep Disorder por BMI Category",
  "BMI Category", "Sleep Disorder"
)

mosaicplot(table(datos2$BMI.Category, datos2$Sleep.Disorder),
           main = "BMI Category vs Sleep Disorder",
           color = TRUE)

Interpretación: el análisis permite explorar si las categorías de IMC presentan patrones diferenciados en la presencia de trastornos del sueño.

6.1.3 Gender vs BMI Category

barras_proporcion(
  datos2, "Gender", "BMI.Category",
  "Proporción de BMI Category por Gender",
  "Gender", "BMI Category"
)

Interpretación: se observa la estructura porcentual del IMC dentro de cada género.

6.1.4 Occupation vs Sleep Disorder

barras_proporcion(
  datos2, "Occupation", "Sleep.Disorder",
  "Proporción de Sleep Disorder por Occupation",
  "Occupation", "Sleep Disorder"
) + coord_flip()

Interpretación: permite identificar ocupaciones con distinta composición porcentual de trastornos del sueño.

6.2 6.2 Categórica vs cuantitativa

6.2.1 Gender vs Sleep Duration

boxplot_por_grupo(datos2, "Gender", "Sleep.Duration",
                  "Sleep Duration por Gender",
                  "Gender", "Sleep Duration")

hist_por_grupo(datos2, "Sleep.Duration", "Gender",
               "Histograma de Sleep Duration por Gender",
               "Sleep Duration", "Gender")

densidad_por_grupo(datos2, "Sleep.Duration", "Gender",
                   "Densidad de Sleep Duration por Gender",
                   "Sleep Duration", "Gender")

Interpretación: la comparación permite establecer si la duración del sueño presenta diferencias de nivel, dispersión y forma entre hombres y mujeres.

6.2.2 Gender vs Stress Level

boxplot_por_grupo(datos2, "Gender", "Stress.Level",
                  "Stress Level por Gender",
                  "Gender", "Stress Level")

hist_por_grupo(datos2, "Stress.Level", "Gender",
               "Histograma de Stress Level por Gender",
               "Stress Level", "Gender")

densidad_por_grupo(datos2, "Stress.Level", "Gender",
                   "Densidad de Stress Level por Gender",
                   "Stress Level", "Gender")

Interpretación: esta comparación facilita examinar si el nivel de estrés tiende a ser distinto según el género.

6.2.3 Gender vs Heart Rate

boxplot_por_grupo(datos2, "Gender", "Heart.Rate",
                  "Heart Rate por Gender",
                  "Gender", "Heart Rate")

hist_por_grupo(datos2, "Heart.Rate", "Gender",
               "Histograma de Heart Rate por Gender",
               "Heart Rate", "Gender")

densidad_por_grupo(datos2, "Heart.Rate", "Gender",
                   "Densidad de Heart Rate por Gender",
                   "Heart Rate", "Gender")

Interpretación: se revisan diferencias potenciales en la frecuencia cardíaca por género.

6.2.4 Occupation vs Sleep Duration

boxplot_por_grupo(datos2, "Occupation", "Sleep.Duration",
                  "Sleep Duration por Occupation",
                  "Occupation", "Sleep Duration") + coord_flip()

ggplot(datos2, aes(x = Sleep.Duration, fill = Occupation)) +
  geom_histogram(alpha = 0.5, position = "identity", bins = 10) +
  facet_wrap(~Occupation) +
  labs(title = "Histograma de Sleep Duration por Occupation",
       x = "Sleep Duration", y = "Frecuencia", fill = "Occupation")

densidad_por_grupo(datos2, "Sleep.Duration", "Occupation",
                   "Densidad de Sleep Duration por Occupation",
                   "Sleep Duration", "Occupation")

Interpretación: estas gráficas permiten comparar la duración del sueño entre ocupaciones, tanto en tendencia central como en forma distributiva.

6.2.5 Occupation vs Stress Level

boxplot_por_grupo(datos2, "Occupation", "Stress.Level",
                  "Stress Level por Occupation",
                  "Occupation", "Stress Level") + coord_flip()

ggplot(datos2, aes(x = Stress.Level, fill = Occupation)) +
  geom_histogram(alpha = 0.5, position = "identity", bins = 8) +
  facet_wrap(~Occupation) +
  labs(title = "Histograma de Stress Level por Occupation",
       x = "Stress Level", y = "Frecuencia", fill = "Occupation")

densidad_por_grupo(datos2, "Stress.Level", "Occupation",
                   "Densidad de Stress Level por Occupation",
                   "Stress Level", "Occupation")

Interpretación: la comparación es útil para explorar si ciertas ocupaciones muestran perfiles de estrés más altos que otras.

6.2.6 BMI Category vs Daily Steps

boxplot_por_grupo(datos2, "BMI.Category", "Daily.Steps",
                  "Daily Steps por BMI Category",
                  "BMI Category", "Daily Steps")

hist_por_grupo(datos2, "Daily.Steps", "BMI.Category",
               "Histograma de Daily Steps por BMI Category",
               "Daily Steps", "BMI Category")

densidad_por_grupo(datos2, "Daily.Steps", "BMI.Category",
                   "Densidad de Daily Steps por BMI Category",
                   "Daily Steps", "BMI Category")

Interpretación: estas visualizaciones permiten estudiar si la cantidad de pasos diarios difiere según la categoría de IMC.

6.2.7 Sleep Disorder vs Sleep Duration

boxplot_por_grupo(datos2, "Sleep.Disorder", "Sleep.Duration",
                  "Sleep Duration por Sleep Disorder",
                  "Sleep Disorder", "Sleep Duration")

hist_por_grupo(datos2, "Sleep.Duration", "Sleep.Disorder",
               "Histograma de Sleep Duration por Sleep Disorder",
               "Sleep Duration", "Sleep Disorder")

densidad_por_grupo(datos2, "Sleep.Duration", "Sleep.Disorder",
                   "Densidad de Sleep Duration por Sleep Disorder",
                   "Sleep Duration", "Sleep Disorder")

Interpretación: permite verificar si las personas con distintos trastornos del sueño presentan patrones diferenciados en la duración del sueño.

6.2.8 Sleep Disorder vs Quality of Sleep

boxplot_por_grupo(datos2, "Sleep.Disorder", "Quality.of.Sleep",
                  "Quality of Sleep por Sleep Disorder",
                  "Sleep Disorder", "Quality of Sleep")

hist_por_grupo(datos2, "Quality.of.Sleep", "Sleep.Disorder",
               "Histograma de Quality of Sleep por Sleep Disorder",
               "Quality of Sleep", "Sleep Disorder")

densidad_por_grupo(datos2, "Quality.of.Sleep", "Sleep.Disorder",
                   "Densidad de Quality of Sleep por Sleep Disorder",
                   "Quality of Sleep", "Sleep Disorder")

Interpretación: este análisis revela diferencias esperables en la calidad del sueño entre quienes presentan o no trastornos.

6.2.9 Sleep Disorder vs Stress Level

boxplot_por_grupo(datos2, "Sleep.Disorder", "Stress.Level",
                  "Stress Level por Sleep Disorder",
                  "Sleep Disorder", "Stress Level")

hist_por_grupo(datos2, "Stress.Level", "Sleep.Disorder",
               "Histograma de Stress Level por Sleep Disorder",
               "Stress Level", "Sleep Disorder")

densidad_por_grupo(datos2, "Stress.Level", "Sleep.Disorder",
                   "Densidad de Stress Level por Sleep Disorder",
                   "Stress Level", "Sleep Disorder")

Interpretación: estas gráficas permiten examinar la posible relación entre trastornos del sueño y niveles de estrés.

6.3 6.3 Cuantitativa vs cuantitativa

6.3.1 Sleep Duration vs Quality of Sleep

scatter_tendencia(datos2, "Sleep.Duration", "Quality.of.Sleep",
                  "Sleep Duration vs Quality of Sleep",
                  "Sleep Duration", "Quality of Sleep")

Interpretación: se espera una asociación positiva, en la que mayor duración del sueño tienda a acompañarse de una mejor calidad del sueño.

6.3.2 Sleep Duration vs Stress Level

scatter_tendencia(datos2, "Sleep.Duration", "Stress.Level",
                  "Sleep Duration vs Stress Level",
                  "Sleep Duration", "Stress Level")

Interpretación: la tendencia suele esperarse negativa, en la medida en que una menor duración del sueño podría asociarse con niveles más altos de estrés.

6.3.3 Physical Activity Level vs Daily Steps

scatter_tendencia(datos2, "Physical.Activity.Level", "Daily.Steps",
                  "Physical Activity Level vs Daily Steps",
                  "Physical Activity Level", "Daily Steps")

Interpretación: se espera una asociación positiva, ya que mayores niveles de actividad física deberían reflejarse en mayor número de pasos diarios.

6.3.4 Physical Activity Level vs Heart Rate

scatter_tendencia(datos2, "Physical.Activity.Level", "Heart.Rate",
                  "Physical Activity Level vs Heart Rate",
                  "Physical Activity Level", "Heart Rate")

Interpretación: esta relación puede reflejar patrones de acondicionamiento físico, en los que mayor actividad tienda a asociarse con una frecuencia cardíaca menor.

6.3.5 Age vs Systolic

scatter_tendencia(datos2, "Age", "Systolic",
                  "Age vs Systolic",
                  "Age", "Systolic")

Interpretación: esta comparación permite explorar el aumento potencial de la presión sistólica con la edad.

6.3.6 Age vs Diastolic

scatter_tendencia(datos2, "Age", "Diastolic",
                  "Age vs Diastolic",
                  "Age", "Diastolic")

Interpretación: se analiza si la presión diastólica muestra un patrón sistemático de cambio con la edad.

6.3.7 Stress Level vs Systolic

scatter_tendencia(datos2, "Stress.Level", "Systolic",
                  "Stress Level vs Systolic",
                  "Stress Level", "Systolic")

Interpretación: esta visualización resulta útil para examinar si el aumento del estrés se acompaña de valores mayores de presión sistólica.

6.3.8 Stress Level vs Diastolic

scatter_tendencia(datos2, "Stress.Level", "Diastolic",
                  "Stress Level vs Diastolic",
                  "Stress Level", "Diastolic")

Interpretación: permite explorar la asociación entre estrés y presión diastólica.

6.3.9 Heart Rate vs Systolic

scatter_tendencia(datos2, "Heart.Rate", "Systolic",
                  "Heart Rate vs Systolic",
                  "Heart Rate", "Systolic")

Interpretación: el análisis ayuda a revisar la relación conjunta entre dos marcadores cardiovasculares.

6.3.10 Heart Rate vs Diastolic

scatter_tendencia(datos2, "Heart.Rate", "Diastolic",
                  "Heart Rate vs Diastolic",
                  "Heart Rate", "Diastolic")

Interpretación: se observa si la frecuencia cardíaca tiende a acompañarse de cambios en la presión diastólica.

6.3.11 Systolic vs Diastolic

scatter_tendencia(datos2, "Systolic", "Diastolic",
                  "Systolic vs Diastolic",
                  "Systolic", "Diastolic")

Interpretación: esta relación es fundamental para revisar la coherencia interna de la variable de presión arterial.

6.4 6.4 Correlación entre variables cuantitativas

matriz_cor <- cor(datos2[, cuantitativas], use = "complete.obs")
knitr::kable(round(matriz_cor, 3), caption = "Matriz de correlación de variables cuantitativas")
Matriz de correlación de variables cuantitativas
Age Sleep.Duration Quality.of.Sleep Physical.Activity.Level Stress.Level Heart.Rate Daily.Steps Systolic Diastolic
Age 1.000 0.345 0.474 0.179 -0.422 -0.226 0.058 0.606 0.594
Sleep.Duration 0.345 1.000 0.883 0.212 -0.811 -0.516 -0.040 -0.180 -0.167
Quality.of.Sleep 0.474 0.883 1.000 0.193 -0.899 -0.660 0.017 -0.122 -0.110
Physical.Activity.Level 0.179 0.212 0.193 1.000 -0.034 0.137 0.773 0.265 0.383
Stress.Level -0.422 -0.811 -0.899 -0.034 1.000 0.670 0.187 0.103 0.092
Heart.Rate -0.226 -0.516 -0.660 0.137 0.670 1.000 -0.030 0.294 0.271
Daily.Steps 0.058 -0.040 0.017 0.773 0.187 -0.030 1.000 0.103 0.242
Systolic 0.606 -0.180 -0.122 0.265 0.103 0.294 0.103 1.000 0.973
Diastolic 0.594 -0.167 -0.110 0.383 0.092 0.271 0.242 0.973 1.000
cor_df <- as.data.frame(as.table(matriz_cor))
ggplot(cor_df, aes(Var1, Var2, fill = Freq)) +
  geom_tile(color = "white") +
  geom_text(aes(label = round(Freq, 2)), size = 3) +
  labs(title = "Mapa de calor de correlaciones",
       x = "", y = "", fill = "Correlación") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Interpretación: la matriz de correlación resume la intensidad y dirección de las asociaciones lineales entre variables cuantitativas.

7 7. Análisis de normalidad

El análisis de normalidad se realiza únicamente sobre variables cuantitativas. Dado que la prueba de Shapiro-Wilk es sensible al tamaño muestral, sus resultados deben complementarse con la inspección visual del gráfico QQ.

7.1 7.1 Prueba de Shapiro-Wilk

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

for (v in cuantitativas) {
  x <- datos2[[v]]
  x <- x[!is.na(x)]
  prueba <- shapiro.test(x)
  resultados_shapiro <- rbind(
    resultados_shapiro,
    data.frame(
      Variable = v,
      W = unname(prueba$statistic),
      p_value = prueba$p.value
    )
  )
}

knitr::kable(resultados_shapiro, digits = 5,
             caption = "Resultados de la prueba de Shapiro-Wilk")
Resultados de la prueba de Shapiro-Wilk
Variable W p_value
Age 0.95800 0
Sleep.Duration 0.93577 0
Quality.of.Sleep 0.89386 0
Physical.Activity.Level 0.89943 0
Stress.Level 0.89089 0
Heart.Rate 0.88255 0
Daily.Steps 0.93682 0
Systolic 0.92468 0
Diastolic 0.89405 0

Interpretación: valores de p pequeños sugieren desviaciones respecto a la normalidad. Sin embargo, la decisión final debe apoyarse también en los gráficos QQ y en el contexto analítico.

7.2 7.2 Gráficos QQ

qqnorm(datos2$Age, main = "QQ Plot - Age")
qqline(datos2$Age, col = 2)

qqnorm(datos2$Sleep.Duration, main = "QQ Plot - Sleep Duration")
qqline(datos2$Sleep.Duration, col = 2)

qqnorm(datos2$Quality.of.Sleep, main = "QQ Plot - Quality of Sleep")
qqline(datos2$Quality.of.Sleep, col = 2)

qqnorm(datos2$Physical.Activity.Level, main = "QQ Plot - Physical Activity Level")
qqline(datos2$Physical.Activity.Level, col = 2)

qqnorm(datos2$Stress.Level, main = "QQ Plot - Stress Level")
qqline(datos2$Stress.Level, col = 2)

qqnorm(datos2$Heart.Rate, main = "QQ Plot - Heart Rate")
qqline(datos2$Heart.Rate, col = 2)

qqnorm(datos2$Daily.Steps, main = "QQ Plot - Daily Steps")
qqline(datos2$Daily.Steps, col = 2)

qqnorm(datos2$Systolic, main = "QQ Plot - Systolic")
qqline(datos2$Systolic, col = 2)

qqnorm(datos2$Diastolic, main = "QQ Plot - Diastolic")
qqline(datos2$Diastolic, col = 2)

Interpretación: cuando los puntos siguen aproximadamente la línea recta, la variable presenta un comportamiento compatible con la normalidad. Desviaciones sistemáticas, especialmente en colas, sugieren asimetría o curtosis no normal.

8 8. Modelado

8.1 8.1 Regresión lineal múltiple: Quality of Sleep

Se propone un modelo lineal en el cual la calidad del sueño se explica a partir de la duración del sueño, el nivel de estrés, la actividad física, la edad y la frecuencia cardíaca.

modelo_lm <- lm(
  Quality.of.Sleep ~ Sleep.Duration + Stress.Level +
    Physical.Activity.Level + Age + Heart.Rate,
  data = datos2
)

summary(modelo_lm)
## 
## Call:
## lm(formula = Quality.of.Sleep ~ Sleep.Duration + Stress.Level + 
##     Physical.Activity.Level + Age + Heart.Rate, data = datos2)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.13591 -0.21609  0.00027  0.24799  1.00276 
## 
## Coefficients:
##                          Estimate Std. Error t value Pr(>|t|)    
## (Intercept)              6.752409   0.557074  12.121  < 2e-16 ***
## Sleep.Duration           0.619515   0.043365  14.286  < 2e-16 ***
## Stress.Level            -0.274756   0.022367 -12.284  < 2e-16 ***
## Physical.Activity.Level  0.005457   0.001005   5.428 1.03e-07 ***
## Age                      0.014613   0.002480   5.892 8.62e-09 ***
## Heart.Rate              -0.047285   0.006385  -7.405 9.00e-13 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3693 on 368 degrees of freedom
## Multiple R-squared:  0.9061, Adjusted R-squared:  0.9048 
## F-statistic: 710.2 on 5 and 368 DF,  p-value: < 2.2e-16

Interpretación: el modelo permite identificar qué variables explican en mayor medida la variabilidad observada en la calidad del sueño.

8.1.1 Diagnóstico gráfico del modelo lineal

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

par(mfrow = c(1,1))

Interpretación: los gráficos diagnósticos permiten evaluar linealidad, homocedasticidad, normalidad de residuales e influencia de observaciones extremas.

8.2 8.2 Regresión lineal múltiple: Systolic

Se plantea un modelo para la presión sistólica como variable respuesta, usando edad, estrés, frecuencia cardíaca, pasos diarios e IMC como predictores.

modelo_bp <- lm(
  Systolic ~ Age + Stress.Level + Heart.Rate + Daily.Steps + BMI.Category,
  data = datos2
)

summary(modelo_bp)
## 
## Call:
## lm(formula = Systolic ~ Age + Stress.Level + Heart.Rate + Daily.Steps + 
##     BMI.Category, data = datos2)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -13.3627  -2.6842   0.0382   3.4102  12.8793 
## 
## Coefficients:
##                          Estimate Std. Error t value Pr(>|t|)    
## (Intercept)            99.0754610  6.9541499  14.247  < 2e-16 ***
## Age                     0.4342674  0.0383989  11.309  < 2e-16 ***
## Stress.Level            0.9230477  0.2324127   3.972 8.59e-05 ***
## Heart.Rate             -0.0201761  0.1103424  -0.183    0.855    
## Daily.Steps             0.0006511  0.0001522   4.278 2.41e-05 ***
## BMI.CategoryObese      17.8808184  2.2172223   8.065 1.05e-14 ***
## BMI.CategoryOverweight  6.7912873  0.6311671  10.760  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 4.25 on 367 degrees of freedom
## Multiple R-squared:  0.7039, Adjusted R-squared:  0.6991 
## F-statistic: 145.4 on 6 and 367 DF,  p-value: < 2.2e-16

Interpretación: este modelo permite explorar factores asociados con el comportamiento de la presión sistólica.

9 9. Conclusiones

El análisis desarrollado permite integrar varias dimensiones del comportamiento del sueño y del estilo de vida presentes en la base. Las visualizaciones univariadas permiten comprender la estructura básica de las variables, mientras que las visualizaciones bivariadas facilitan la identificación de patrones comparativos y asociaciones relevantes. El análisis de normalidad muestra que no todas las variables cuantitativas necesariamente siguen una distribución normal, aspecto que debe considerarse en el uso de procedimientos inferenciales. Finalmente, los modelos planteados muestran ejemplos coherentes de aplicación de regresión lineal y logística para explicar calidad del sueño, presión arterial y presencia de trastornos del sueño.