Se cargó la base de datos.
datos <- read.csv("mental_health_social_media_dataset.csv", header= T)
library(tidyverse)
datos <- datos %>%
mutate(date = as.Date(date,format="%m/%d/%Y")) %>%
arrange(date)
Se utlizó skim() para tener una mejor visión de la
base de datos.
library(skimr)
skimr::skim(datos)
Data summary
| Name |
datos |
| Number of rows |
5000 |
| Number of columns |
15 |
| _______________________ |
|
| Column type frequency: |
|
| character |
4 |
| Date |
1 |
| numeric |
10 |
| ________________________ |
|
| Group variables |
None |
Variable type: character
| person_name |
0 |
1 |
7 |
17 |
0 |
891 |
0 |
| gender |
0 |
1 |
4 |
6 |
0 |
3 |
0 |
| platform |
0 |
1 |
6 |
9 |
0 |
7 |
0 |
| mental_state |
0 |
1 |
7 |
8 |
0 |
3 |
0 |
Variable type: Date
| date |
0 |
1 |
2024-01-01 |
2025-11-16 |
2024-12-09 |
686 |
Variable type: numeric
| age |
0 |
1 |
29.95 |
12.28 |
13.0 |
21.0 |
27.0 |
35.25 |
69.0 |
▇▆▃▁▁ |
| daily_screen_time_min |
0 |
1 |
373.06 |
106.00 |
140.0 |
310.0 |
388.0 |
461.00 |
520.0 |
▃▃▃▅▇ |
| social_media_time_min |
0 |
1 |
175.33 |
71.21 |
35.0 |
118.0 |
170.0 |
231.00 |
338.0 |
▃▇▇▅▃ |
| negative_interactions_count |
0 |
1 |
0.86 |
0.56 |
0.0 |
1.0 |
1.0 |
1.00 |
2.0 |
▃▁▇▁▁ |
| positive_interactions_count |
0 |
1 |
1.84 |
0.94 |
0.0 |
1.0 |
2.0 |
2.00 |
4.0 |
▁▇▆▃▁ |
| sleep_hours |
0 |
1 |
7.13 |
0.53 |
6.4 |
6.7 |
7.1 |
7.45 |
8.3 |
▇▆▅▃▃ |
| physical_activity_min |
0 |
1 |
22.69 |
10.60 |
8.0 |
14.0 |
21.0 |
29.00 |
46.0 |
▇▆▃▃▃ |
| anxiety_level |
0 |
1 |
2.51 |
0.79 |
1.0 |
2.0 |
3.0 |
3.00 |
4.0 |
▂▇▁▇▂ |
| stress_level |
0 |
1 |
7.11 |
1.06 |
5.0 |
6.0 |
7.0 |
8.00 |
9.0 |
▂▅▇▇▂ |
| mood_level |
0 |
1 |
5.63 |
0.76 |
4.0 |
5.0 |
6.0 |
6.00 |
7.0 |
▁▆▁▇▂ |
La base de datos contiene 15 columnas y 5,000 filas. También se
puede ver que el n_missing de cada columna tiene una
cantidad de cero, lo cual significa que no hay datos faltantes. A
continuación, se hizo una gráfica para tener certeza.
# NA por columna
library(naniar)
gg_miss_var(datos)

Ahora estariamos escalando las variables. La variable de
stress_level, al ser la dependiente, no se escala. Escalamos todas las
variables numéricas, y convertimos las categóricas a factor.
library(scales)
datos_esc <- datos %>%
mutate(
across(where(is.numeric) & !c(stress_level), rescale),
gender = as.factor(gender),
platform = as.factor(platform),
mental_state = as.factor(mental_state)
)
# Variables categóricas
datos_esc$gender <- relevel(datos_esc$gender, ref = "Male")
datos_esc$mental_state <- relevel(datos_esc$mental_state, ref = "Healthy")
Regresión lineal simple
Un valor de correlación de 0.8829 es una relación fuerte y postiva
entre el nivel de estrés y el tiempo en redes sociales en minutos.
Modelo de regresión lineal simple
lm <- lm(stress_level ~ social_media_time_min, data = datos_esc)
summary(lm)
##
## Call:
## lm(formula = stress_level ~ social_media_time_min, data = datos_esc)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.97047 -0.39301 -0.01312 0.38412 1.05483
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 5.25920 0.01559 337.2 <2e-16 ***
## social_media_time_min 3.99102 0.03003 132.9 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.499 on 4998 degrees of freedom
## Multiple R-squared: 0.7795, Adjusted R-squared: 0.7794
## F-statistic: 1.767e+04 on 1 and 4998 DF, p-value: < 2.2e-16
En el modelo de regresión lineal simple se analizó la relación entre
el nivel de estrés y el tiempo en redes sociales en minutos, obteniendo
un intercepto de 5.26, lo que indica que cuando el tiempo en redes
sociales es cero, el nivel de estrés promedio es de 5.26 unidades. El
coeficiente de la variable fue de 3.99, lo que sugiere que por cada
unidad adicional en el tiempo dedicado a redes sociales (en escala
estandarizada), el nivel de estrés aumenta en promedio 3.99 unidades,
manteniendo constante el resto del contexto. Este efecto fue altamente
significativo, con un p-value menor a 2e-16, lo que indica una relación
confiable. Además, el modelo presentó un R² ajustado de 0.779, lo que
significa que el tiempo en redes sociales explica aproximadamente el
77.9% de la variación en el nivel de estrés. Estos hallazgos sugieren
que el tiempo en redes sociales es un predictor fuerte del estrés
percibido, y sirven como punto de partida sólido para desarrollar
modelos más complejos en las siguientes etapas del proyecto.
Regresión lineal múltiple
El método siguiente a utilizarse es el de la regresión lineal
múltiple (RLM). Ya vimos la relación entre las variables de stress_level
y social_media_time_min, pero ahora se añadiran variables adicionales
para ir más al detalle con la investigación.
1. Ajuste del modelo:
Se va a evaluar que modelo vamos a escoger entre: el modelo por
subconjuntos y el modelo paso a paso.
A. Modelo por subconjuntos:
Se calculó el modelo saturado, en donde se encuentran todas las
variables que utilizaremos.
saturado <- stress_level ~ age + gender + platform +
negative_interactions_count + positive_interactions_count +
sleep_hours + physical_activity_min + anxiety_level + mood_level +
social_media_time_min + daily_screen_time_min + mental_state
reg <- lm(saturado, data = datos_esc)
summary(reg)
##
## Call:
## lm(formula = saturado, data = datos_esc)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.70481 -0.11100 0.00745 0.11117 0.63137
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 7.904920 0.433933 18.217 < 2e-16 ***
## age -0.325658 0.026896 -12.108 < 2e-16 ***
## genderFemale -0.007434 0.005700 -1.304 0.192216
## genderOther -0.017063 0.020460 -0.834 0.404335
## platformInstagram 0.001181 0.019190 0.062 0.950945
## platformSnapchat -0.039973 0.022586 -1.770 0.076820 .
## platformTikTok -0.070660 0.031822 -2.220 0.026432 *
## platformTwitter 0.072790 0.012353 5.893 4.05e-09 ***
## platformWhatsApp 0.022665 0.014812 1.530 0.126032
## platformYouTube -0.082463 0.027258 -3.025 0.002497 **
## negative_interactions_count 0.322541 0.022045 14.631 < 2e-16 ***
## positive_interactions_count -0.010834 0.039325 -0.276 0.782938
## sleep_hours -0.016344 0.187918 -0.087 0.930697
## physical_activity_min -1.247074 0.371993 -3.352 0.000807 ***
## anxiety_level 0.724819 0.034020 21.306 < 2e-16 ***
## mood_level -1.590849 0.030426 -52.285 < 2e-16 ***
## social_media_time_min 0.542346 0.084197 6.441 1.30e-10 ***
## daily_screen_time_min -0.245255 0.435250 -0.563 0.573132
## mental_stateAt_Risk -0.260604 0.028820 -9.042 < 2e-16 ***
## mental_stateStressed 0.079276 0.016919 4.686 2.87e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.1992 on 4980 degrees of freedom
## Multiple R-squared: 0.965, Adjusted R-squared: 0.9648
## F-statistic: 7221 on 19 and 4980 DF, p-value: < 2.2e-16
Selección de modelo por subconjunto:
library(leaps)
ajuste <- regsubsets(
saturado,
data = datos_esc,
nvmax = 7,
method = "exhaustive")
s <- summary(ajuste)
names(s)
## [1] "which" "rsq" "rss" "adjr2" "cp" "bic" "outmat" "obj"
Se identificó el mejor modelo entre BIC y R^2 ajustado.
best_bic <- which.min(s$bic)
best_r2 <- which.max(s$adjr2)
# Visualización comparativa
par(mfrow = c(1,2))
plot(s$bic, type="b", col="red", pch=19,
xlab="Número de predictores", ylab="BIC",
main="Criterio BIC")
points(best_bic, s$bic[best_bic], pch=19, cex=1.5, col="blue")
plot(s$adjr2, type="b", col="darkgreen", pch=19,
xlab="Número de predictores", ylab="R^2-ajustado",
main="Criterio R^2-ajustado")
points(best_r2, s$adjr2[best_r2], pch=19, cex=1.5, col="blue")

El modelo saturado mostró un R2 ajustado de 0.9648, indicando que
tiene una capacidad alta de explicar las variables. Aparte de esto, se
aplicó la selección de variables por subconjunto, estos siendo el BIC y
el R2 ajustado. Ambos criterios coincidieron en la selección de 7
predictores, lo que sugiere un equilibrio entre ajuste y parsimonia. El
resultado nos asegura que el nivel de estrés si esta determinado por
varias de estas variables; tales como: el estado mental, las
interacciones negativas en las redes, la actividad física, entre
otros.
B. Modelo paso a paso:
Se utlizó el mismo modelo saturado del ajuste de modelo de
subconjuntos, y se calculó el modelo nulo.
saturado <- stress_level ~ age + gender + platform +
negative_interactions_count + positive_interactions_count +
sleep_hours + physical_activity_min + anxiety_level + mood_level +
social_media_time_min + daily_screen_time_min + mental_state
reg <- lm(saturado, data = datos_esc)
nulo <- lm(stress_level ~ 1, data = datos_esc)
Forward stepwise selection:
step_forward <- step(nulo,
scope = list(lower = ~1, upper = formula(reg)),
direction = "forward",
k = log(nrow(datos)),
trace = FALSE)
Backward stepwise selection:
step_backward <- step(reg,
direction = "backward",
k = log(nrow(datos)),
trace = FALSE)
Hybrid:
step_both <- step(nulo,
scope = list(lower = ~1, upper = formula(reg)),
direction = "both",
k = log(nrow(datos)),
trace = FALSE)
2. Modelo final (Hybrid):
modelo1 <- step_both
summary(modelo1)
##
## Call:
## lm(formula = stress_level ~ mood_level + physical_activity_min +
## anxiety_level + negative_interactions_count + age + platform +
## mental_state + social_media_time_min, data = datos_esc)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.70032 -0.10999 0.00737 0.11198 0.63574
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 7.661344 0.057998 132.097 < 2e-16 ***
## mood_level -1.592604 0.030387 -52.411 < 2e-16 ***
## physical_activity_min -1.023652 0.048893 -20.936 < 2e-16 ***
## anxiety_level 0.721797 0.033331 21.656 < 2e-16 ***
## negative_interactions_count 0.323722 0.021722 14.903 < 2e-16 ***
## age -0.325112 0.026757 -12.150 < 2e-16 ***
## platformInstagram 0.001334 0.018450 0.072 0.94239
## platformSnapchat -0.037440 0.022209 -1.686 0.09190 .
## platformTikTok -0.066949 0.031363 -2.135 0.03284 *
## platformTwitter 0.073232 0.012328 5.940 3.04e-09 ***
## platformWhatsApp 0.021752 0.014688 1.481 0.13868
## platformYouTube -0.082002 0.026233 -3.126 0.00178 **
## mental_stateAt_Risk -0.260603 0.028617 -9.107 < 2e-16 ***
## mental_stateStressed 0.079192 0.016869 4.695 2.74e-06 ***
## social_media_time_min 0.525983 0.075281 6.987 3.18e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.1992 on 4985 degrees of freedom
## Multiple R-squared: 0.965, Adjusted R-squared: 0.9649
## F-statistic: 9805 on 14 and 4985 DF, p-value: < 2.2e-16
En el modelo final se obtuvo un intercepto de 7.66,
lo que indica que el nivel esperado de estrés es de
7.66 unidades cuando todas las variables explicativas
son cero y las categorías base de las variables categóricas están
presentes.
mood_level: es de −1.59, lo que
sugiere que, por cada unidad adicional en el nivel de estado de ánimo,
el nivel de estrés disminuye en promedio 1.59 unidades, manteniendo
constantes las demás variables.
physical_activity_min es de −1.02,
indicando que un aumento en el tiempo dedicado a actividad física se
asocia con una reducción promedio de 1.02 unidades en el nivel de
estrés.
anxiety_level: de 0.72, lo que
implica que por cada unidad adicional de ansiedad, el nivel de estrés
aumenta en promedio 0.72 unidades, manteniendo constantes las demás
variables.
negative_interaction_counts: el número de
interacciones negativas en redes sociales muestra una relación positiva,
ya que por cada interacción negativa adicional, el estrés aumenta en
promedio 0.32 unidades.
age: es de (−0.33), lo que indica
que, a mayor edad, el nivel de estrés tiende a disminuir, manteniendo
constantes las demás variables.
social_media_time_min: es de 0.53,
lo que sugiere que un mayor tiempo de uso está asociado con un aumento
del nivel de estrés.
platform: se observa que el uso de Twitter se
asocia con un nivel de estrés significativamente mayor en comparación
con la plataforma base, mientras que YouTube y TikTok presentan
coeficientes negativos, indicando menores niveles de estrés
promedio.
mental_state: los individuos clasificados como At
Risk o Stressed presentan niveles de estrés significativamente más altos
que aquellos en la categoría base, manteniendo constantes las demás
variables.
El modelo final presenta un R² ajustado de
0.9649, lo cual indica que explica aproximadamente el
96.49% de la variación en el nivel de estrés. Además,
el error estándar residual es cercano a
0.20, lo que sugiere que, en promedio, las predicciones
del modelo difieren del nivel real de estrés en aproximadamente 0.20
unidades.
3. Evaluación de los supuestos:
a. Normalidad
library(ggplot2)
library(broom)
df <- data.frame(
yhat = fitted.values(modelo1),
res = rstandard(modelo1))
ggplot(df, aes(sample = res)) +
stat_qq(color = "blue") +
stat_qq_line(linewidth = 1) +
labs(x = "Cuantiles teóricos", y = "Cuantiles muestrales") +
theme_minimal(base_size = 14)

Prueba Shapiro-Wilk:
shapiro.test(df$res)
##
## Shapiro-Wilk normality test
##
## data: df$res
## W = 0.98294, p-value < 2.2e-16
Cuando analizamos el supuesto de normalidad por medio de la gráfica
Q–Q, podemos observar que la mayoría de los puntos se encuentran cerca
de la línea del modelo, especialmente en la parte central, aunque
existen algunas desviaciones en los extremos. Esto sugiere que los
residuos del modelo se distribuyen de forma aproximadamente normal. Si
tomamos en consideración la Prueba de Shapiro–Wilk, se obtuvo un p-value
menor a 0.05, por lo que se rechaza la H0 de normalidad. No obstante,
debido al tamaño de la muestra y a que las desviaciones observadas en la
gráfica no son severas, se puede concluir que el supuesto de normalidad
se cumple de manera aproximada para fines del análisis del modelo.
b. Varianza constante
ggplot(df, aes(x = yhat, y = res)) +
geom_point(alpha = 0.6, color = "blue") +
geom_hline(yintercept = 0, linetype = "dashed", color = "grey40") +
labs(x = "Valores ajustados", y = "Residuales estandarizados") +
theme_minimal(base_size = 14)

Prueba Breusch-Pagan:
library(lmtest)
bptest(modelo1)
##
## studentized Breusch-Pagan test
##
## data: modelo1
## BP = 1747.2, df = 14, p-value < 2.2e-16
Para que se cumpla el supuesto de varianza constante por el gráfico,
la nube de puntos debe permanecer aproximadamente constante alrededor
del cero, sin presentar patrones definidos. En este caso, aunque los
residuos se distribuyen alrededor del cero, se observa que la dispersión
no es completamente uniforme basado en las líneas que aparecen, lo que
sugiere posibles variaciones en la varianza a lo largo de los valores
ajustados. Para complementar el análisis gráfico, se utilizó la Prueba
de Breusch–Pagan, considerando como H0= la varianza es constante y H1=
la varianza no es constante. Dado que el p-value obtenido es menor a
0.05, se rechaza la hipótesis nula, por lo que el modelo no cumple
completamente con el supuesto de varianza constante.
c. Independencia
library(ggplot2)
library(tidyverse)
df1 <- data.frame(
res = rstandard(modelo1)) %>%
mutate(orden = 1:length(res))
ggplot(df1, aes(x = orden, y = res)) +
geom_point(alpha = 0.6, color = "blue") +
geom_hline(yintercept = 0, linetype = "dashed", color = "grey40") +
labs(x = "Orden/tiempo", y = "Residuales estandarizados") +
theme_minimal(base_size = 14)

Prueba Durbin-Watson:
dwtest(modelo1)
##
## Durbin-Watson test
##
## data: modelo1
## DW = 2.0064, p-value = 0.5939
## alternative hypothesis: true autocorrelation is greater than 0
Para que se cumpla el supuesto de independencia por el gráfico, la
nube de puntos debe distribuirse de forma aleatoria alrededor del cero,
sin mostrar patrones sistemáticos ni tendencias. En este caso, los
residuos se mantienen alrededor del cero y no presentan una estructura
clara, lo que respalda gráficamente el cumplimiento del supuesto de
independencia. Para reforzar, se aplicó la Prueba de Durbin–Watson,
tomando como H0= la independencia de los errores y como H1= la
dependencia/autocorrelación. El resultado arrojó un p-value mayor a
0.05, por lo que no se rechaza la hipótesis nula y se concluye que el
modelo cumple con el supuesto de independencia.
Conclusión:
En este proyecto se analizó la relación entre el nivel de estrés y
el uso de las redes sociales mediante modelos de refresión lineal simple
y múltiple. El modelo de regresión lineal simple mostró que el tiempo
dedicado a las redes sociales es un predictor significativo del nivel de
estrés. Este resultado nos sirvió como base para el desarrollo de modelo
más complejos.
Anteriormente, se habia estimado un modelo de regresión múltiple que
incorporó variables demográficas, conductuales y psicológicas. Mediante
distintos procesos de selección de variables (modelos por subconjunto y
paso a paso), se pudo identificar que el modelo híbrido ofrecía
coeficientes significativos alto y un R^2 ajustado elevado. Se terminó
cumpliendo con los supuestos de normalidad e independencia, pero no se
pudo cumplir el de varianza.
En conjunto, los resultados sugieren que el nivel de estrés esta
influenciado no solo por el tiempo en las redes sociales, sino tambien
por factores psicológicos, las experiencias negativas en las redes y
hábitos de bienestar como la actividad física. Estos hallazgos resaltan
la importancia de considerar varias variables al analizar el estrés que
es percibido.
social_media_time_min: es de 0.53, lo que sugiere que un mayor tiempo de uso está asociado con un aumento del nivel de estrés.