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.
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
##
##
##
# 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 ...
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")
| 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 |
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.
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)
}
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.
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.
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.
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.
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"
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
matriz_cor <- cor(datos2[, cuantitativas], use = "complete.obs")
knitr::kable(round(matriz_cor, 3), caption = "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.
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.
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")
| 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.
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.
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.
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.
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.
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.