Laboratorio guiado en R

Entendiendo la regresión lineal

¿Puede una recta ayudarnos a comprender la relación entre movilidad y estrés?

Datos160 estudiantes ficticios
SoftwareR o RStudio
ProductoCódigo + interpretación

Antes de comenzar: ¿qué vas a hacer?

Este es un laboratorio práctico y guiado. No está diseñado para leerlo de principio a fin sin detenerse: la idea es que avances en orden, ejecutes en R el código de cada sección, observes cuidadosamente los resultados y respondas las preguntas antes de pasar al siguiente paso.

Mientras sigues esta guía, debes construir tu propio archivo R Markdown. Ese archivo será tu cuaderno de trabajo y, al terminar, se convertirá en un informe completo del ejercicio. Allí debes integrar:

Piensa en el resultado final como un informe, no como una colección de respuestas sueltas. Una persona que no estuvo en clase debería poder abrirlo, entender la pregunta, seguir lo que hiciste y comprender tus conclusiones sin necesidad de mirar este laboratorio.

Pregunta de investigación

¿Cómo se relaciona el tiempo diario de desplazamiento con el nivel de estrés de estudiantes universitarios?

Trabajaremos con una encuesta simulada de estudiantes universitarios de Cali. Los datos fueron creados únicamente con fines pedagógicos y no describen una población real.

Descargar la base CSV
Regla central del laboratorio. No basta con mostrar código o copiar la salida de R. Después de cada análisis debes explicar: qué hiciste, qué encontraste y qué significa en el contexto del problema.

Una respuesta como “el coeficiente es significativo” está incompleta. Una respuesta adecuada identifica la variable, la dirección, la magnitud, la unidad y la conclusión que permiten los datos.

1. Objetivos de aprendizaje

Al finalizar, deberías poder explicar con tus propias palabras:

Qué debes entregar: el informe generado desde tu archivo R Markdown, bien organizado y presentado. Debe contener un título, tu nombre, secciones con encabezados, respuestas numeradas, código legible, tablas o gráficos pertinentes y una conclusión final. Ningún resultado de R debe aparecer sin una explicación que indique qué muestra y por qué es importante.

2. Preparación del trabajo

Antes de analizar los datos, crea el documento en el que desarrollarás todo el laboratorio. No trabajes únicamente en la consola: la consola sirve para probar, pero tu análisis debe quedar registrado y poder reproducirse.

  1. Guarda este HTML y movilidad_estudiantes.csv en la misma carpeta.
  2. Abre RStudio y crea un archivo nuevo desde File → New File → R Markdown.
  3. Escribe un título descriptivo, tu nombre y la fecha. Selecciona HTML como formato de salida.
  4. Guarda el archivo .Rmd en la misma carpeta que la base de datos.
  5. Organiza el documento con encabezados que correspondan a las secciones de este laboratorio.
  6. Usa bloques de código para ejecutar R y texto normal para explicar lo que hiciste y lo que significan los resultados.
  7. Carga tidyverse e importa la base en el primer bloque de código.

Tu archivo puede comenzar con una estructura similar a esta:

---
title: "Laboratorio: entendiendo la regresión lineal"
author: "Tu nombre"
date: "Fecha de entrega"
output: html_document
---

# Pregunta de investigación

En esta sección explicaré qué relación vamos a estudiar y por qué.

```{r preparacion, message=FALSE, warning=FALSE}
library(tidyverse)
datos <- read.csv("movilidad_estudiantes.csv")
```

# Conociendo los datos

Aquí incluiré el código solicitado y explicaré los resultados.
Cómo avanzar en cada sección. Sigue siempre este ciclo: leer la pregunta → anticipar qué esperas encontrar → ejecutar el código → observar el resultado → explicarlo en tu R Markdown. No pases a la siguiente sección hasta poder decir con tus propias palabras qué acabas de hacer.
# Instálalo una sola vez si no lo tienes:
# install.packages("tidyverse")

library(tidyverse)

datos <- read.csv("movilidad_estudiantes.csv")
Comprobación. Si nrow(datos) devuelve 160 y ncol(datos) devuelve 6, la importación fue correcta. Si no ocurre, revisa la carpeta y el nombre del archivo antes de continuar.
Revisa tu documento durante el proceso. Usa el botón Knit con frecuencia, no solamente al final. Así podrás detectar a tiempo errores de código, títulos desordenados, gráficos difíciles de leer o explicaciones que quedaron incompletas.

3. Conocer los datos

VariableDescripciónUnidad o valores
idIdentificador de la persona1 a 160
tiempo_viajeDesplazamiento total en un día habitualMinutos
estresÍndice de estrés0 a 100
transbordosNúmero habitual de transbordos0 a 3
seguridadPercepción de seguridad durante el viaje1 a 10
cuidadoResponsabilidades habituales de cuidado1 = sí; 0 = no
head(datos)
glimpse(datos)
summary(datos)
Actividad 3.
  1. ¿Cuántas observaciones tiene la base? ¿Qué representa una observación?
  2. Clasifica las variables como identificadora, cuantitativa o categórica. ¿Por qué cuidado, aunque use números, representa categorías?
  3. Para la pregunta de investigación, identifica la variable dependiente Y y la variable independiente principal X.
  4. Explica por qué una es la variable que queremos comprender y la otra es la variable explicativa.

4. Inspeccionar antes de modelar

Una regresión no debe comenzar con lm(...). Primero debemos saber qué estamos modelando, revisar rangos y detectar datos imposibles o ausentes.

# Valores ausentes por variable
colSums(is.na(datos))

# Estadísticos centrales y dispersión
datos %>%
  summarise(
    n = n(),
    promedio_viaje = mean(tiempo_viaje),
    mediana_viaje = median(tiempo_viaje),
    minimo_viaje = min(tiempo_viaje),
    maximo_viaje = max(tiempo_viaje),
    promedio_estres = mean(estres),
    sd_estres = sd(estres)
  )

# Frecuencias de variables discretas
count(datos, transbordos)
count(datos, cuidado)
Actividad 4.
  1. ¿Hay valores ausentes?
  2. Describe la muestra en un párrafo. Integra los números en oraciones: no pegues solamente la tabla.
  3. ¿Los rangos observados son compatibles con las descripciones de las variables?
  4. ¿Cuál es la diferencia entre la desviación estándar del estrés y su promedio?

5. Ver la relación antes de estimarla

Comienza con los puntos, sin recta. Cada punto representa una persona.

ggplot(datos, aes(x = tiempo_viaje, y = estres)) +
  geom_point(alpha = 0.65, color = "#165d70") +
  labs(
    x = "Tiempo diario de desplazamiento (minutos)",
    y = "Índice de estrés",
    title = "Tiempo de desplazamiento y estrés"
  ) +
  theme_minimal()
Actividad 5. Lee el gráfico.
  1. Dirección: ¿la relación parece positiva, negativa o inexistente?
  2. Forma: ¿parece aproximadamente lineal o presenta una curva?
  3. Intensidad: ¿los puntos están muy agrupados o existe dispersión?
  4. Casos inusuales: ¿observas puntos alejados del patrón general?
  5. Antes de estimar el modelo, predice el signo del coeficiente de tiempo_viaje y justifica.

6. La intuición de una recta

Ahora agrega la recta que resume la tendencia promedio:

ggplot(datos, aes(x = tiempo_viaje, y = estres)) +
  geom_point(alpha = 0.65, color = "#165d70") +
  geom_smooth(method = "lm", se = FALSE, color = "#d8782d") +
  labs(
    x = "Tiempo diario de desplazamiento (minutos)",
    y = "Índice de estrés",
    title = "Una recta para resumir la relación"
  ) +
  theme_minimal()

Yi = β0 + β1Xi + εi

En nuestro caso, β0 es el intercepto, β1 es la pendiente y εi representa la parte del estrés de la persona i que esta recta no explica.

La idea clave. Entre todas las rectas posibles, mínimos cuadrados elige la que hace tan pequeña como sea posible la suma de los residuos elevados al cuadrado.

residuoi = valor observadoi − valor predichoi

Actividad 6. Razona antes de calcular.
  1. ¿Qué significaría una pendiente positiva, una pendiente igual a cero y una pendiente negativa?
  2. Si el estrés observado es 68 y el predicho es 60, calcula e interpreta el residuo.
  3. Si el estrés observado es 55 y el predicho es 63, calcula e interpreta el residuo.
  4. ¿Por qué una sola recta difícilmente predice de manera perfecta el estrés de todas las personas?
  5. ¿Por qué se elevan los residuos al cuadrado en vez de sumarlos directamente?

7. Estimar una regresión lineal simple

modelo1 <- lm(estres ~ tiempo_viaje, data = datos)
summary(modelo1)
Cómo leer la fórmula. En lm(Y ~ X, data = datos), la variable a la izquierda es la que queremos explicar y la variable a la derecha es la explicativa.
Actividad 7.
  1. Escribe la pregunta estadística que representa estres ~ tiempo_viaje.
  2. Identifica en la salida: coeficientes, errores estándar, estadísticos t, p-values, R2 y R2 ajustado.
  3. No interpretes todavía: describe primero dónde aparece cada elemento.

8. Desmontar la ecuación: intercepto y pendiente

coef(modelo1)

Estrés predicho = b0 + b1(Tiempo de viaje)

8.1 El intercepto

El intercepto b0 es el estrés que el modelo predice cuando el tiempo de viaje vale 0 minutos.

Responde.
  1. ¿Cuál es el intercepto?
  2. Escríbelo como una oración completa usando las unidades.
  3. ¿Es una interpretación sustantivamente útil? Revisa si 0 está dentro del rango observado de tiempo_viaje.

8.2 La pendiente

La pendiente b1 indica cuánto cambia el estrés esperado cuando el tiempo de viaje aumenta una unidad, aquí un minuto.

# Efecto asociado con 10 y 30 minutos adicionales
coef(modelo1)["tiempo_viaje"] * 10
coef(modelo1)["tiempo_viaje"] * 30
Responde.
  1. ¿Cuál es la pendiente y cuál es su signo?
  2. Interprétala por cada minuto adicional de desplazamiento.
  3. Interprétala nuevamente por cada 10 minutos adicionales.
  4. ¿Cuántos puntos de estrés están asociados con 30 minutos adicionales? ¿Te parece una magnitud sustantivamente pequeña o importante en una escala de 0 a 100? Justifica.
  5. Escribe la ecuación completa de tu modelo con los valores estimados.
Cuidado con el lenguaje. En este modelo observacional, “se asocia con” o “el modelo predice” es más correcto que “produce” o “causa”.

9. Usar la recta para predecir

Calcula primero a mano el estrés predicho para 60 minutos usando tu ecuación. Después comprueba:

predict(
  modelo1,
  newdata = data.frame(tiempo_viaje = 60)
)

predict(
  modelo1,
  newdata = data.frame(
    tiempo_viaje = c(30, 60, 90, 120)
  )
)
Actividad 9.
  1. Muestra el cálculo manual para 60 minutos. ¿Coincide con R?
  2. Reporta el estrés esperado para 30 y 120 minutos.
  3. ¿Significa la predicción para 60 minutos que todas las personas con ese viaje tienen exactamente ese estrés? Explica.
  4. ¿Sería razonable usar la ecuación para predecir el estrés de alguien que viaja 300 minutos? Relaciona tu respuesta con el rango de los datos y la idea de extrapolación.

10. Valores observados, predicciones y residuos

datos <- datos %>%
  mutate(
    prediccion = fitted(modelo1),
    residuo = residuals(modelo1)
  )

datos %>%
  select(id, tiempo_viaje, estres, prediccion, residuo) %>%
  slice_head(n = 10)
Signo del residuo. Un residuo positivo indica que el modelo subestimó el valor observado; uno negativo indica que lo sobreestimó.
Actividad 10.
  1. Escoge una de las primeras diez personas y reporta su ID, tiempo, estrés observado, estrés predicho y residuo.
  2. Comprueba manualmente que estres - prediccion = residuo.
  3. Interpreta el signo y la magnitud del residuo para esa persona.
  4. Identifica el residuo con mayor valor absoluto. ¿Debemos eliminar automáticamente esa observación? ¿Por qué?
  5. Propón al menos tres razones por las que dos personas con el mismo tiempo de viaje podrían tener diferente estrés.
datos %>%
  slice_max(order_by = abs(residuo), n = 1)

11. Incertidumbre: p-values e intervalos de confianza

11.1 ¿La pendiente podría ser cero en la población?

Para tiempo_viaje, la prueba de la salida de summary(modelo1) contrasta:

H0: β1 = 0    frente a    H1: β1 ≠ 0

Un p-value pequeño indica que el resultado observado sería poco compatible con H0, bajo los supuestos del modelo. No es la probabilidad de que H0 sea verdadera y no mide el tamaño o la importancia del efecto.

Actividad 11A.
  1. Reporta el p-value de tiempo_viaje.
  2. Con α = 0.05, ¿rechazas o no rechazas H0?
  3. Escribe la conclusión como evidencia sobre una asociación lineal entre las variables, sin afirmar causalidad.
  4. Explica por qué significancia estadística e importancia sustantiva no son sinónimos.

11.2 Un rango plausible para el coeficiente

confint(modelo1, level = 0.95)
Actividad 11B.
  1. Reporta el intervalo de confianza del 95% para tiempo_viaje.
  2. ¿Incluye cero? ¿Cómo se relaciona esto con la prueba al 5%?
  3. Interpreta el intervalo con las variables y unidades concretas del estudio.
  4. ¿Por qué es más informativo reportar estimación e intervalo que solamente el p-value?

12. ¿Cuánto logra explicar el modelo? R2

R2 es la proporción de la variabilidad observada en la variable dependiente que queda explicada por el modelo, dentro de esta muestra.

No significa “porcentaje de predicciones correctas”, “porcentaje de causalidad” ni “porcentaje de verdad del modelo”.
summary(modelo1)$r.squared
summary(modelo1)$adj.r.squared
Actividad 12.
  1. Reporta e interpreta R2 usando tiempo de viaje y estrés.
  2. ¿Qué porcentaje de la variabilidad queda sin explicar?
  3. ¿Un R2 menor que 1 significa necesariamente que el modelo es malo? Responde pensando en fenómenos sociales.
  4. ¿Puede un modelo tener R2 alto y aun así ser conceptualmente inadecuado? Da un ejemplo o una razón.

13. Examinar los supuestos del modelo

Los diagnósticos no son una ceremonia posterior al análisis: ayudan a decidir si una recta y la inferencia asociada son razonables.

par(mfrow = c(2, 2))
plot(modelo1)
par(mfrow = c(1, 1))

13.1 Linealidad

En Residuals vs Fitted, buscamos residuos alrededor de cero sin una curva sistemática.

13.2 Homocedasticidad

La dispersión vertical de los residuos debería ser aproximadamente constante, sin una forma clara de embudo. El gráfico Scale-Location también ayuda a verla.

13.3 Normalidad aproximada de los residuos

En Normal Q-Q, los puntos deberían seguir aproximadamente la diagonal. Pequeñas desviaciones no implican automáticamente que el análisis sea inútil.

13.4 Casos influyentes e independencia

Residuals vs Leverage ayuda a detectar observaciones que podrían influir mucho en la recta. La independencia, en cambio, se evalúa principalmente con el diseño: cada fila debe aportar información independiente de las demás.

Actividad 13.
  1. ¿Observas una curva evidente en los residuos?
  2. ¿La dispersión parece aproximadamente constante o hay un embudo?
  3. ¿El gráfico Q-Q muestra desviaciones graves?
  4. ¿Hay casos que merezcan revisión por residuo o influencia?
  5. ¿Qué información sobre la recolección necesitarías para evaluar independencia?
  6. Redacta un diagnóstico global prudente. Evita decir simplemente “se cumplen todos los supuestos”.
No elimines casos de forma automática. Un valor inusual puede ser un error, una observación válida o una señal de que falta algo importante en el modelo. Primero se investiga.

14. Asociación no es lo mismo que causalidad

Aunque encontremos que quienes viajan más tienden a reportar mayor estrés, la regresión simple no demuestra que una variable cause la otra. Pueden existir variables que estén relacionadas con ambas.

Actividad 14.
  1. Propón tres posibles variables de confusión que no estén medidas en la base.
  2. Explica cómo cada una podría relacionarse simultáneamente con tiempo de viaje y estrés.
  3. De las variables disponibles, ¿cuáles podrían ayudar a describir mejor la relación?
  4. ¿Qué tipo de diseño o información adicional fortalecería una afirmación causal?

15. De la regresión simple a la múltiple

modelo2 <- lm(
  estres ~ tiempo_viaje + transbordos + seguridad + cuidado,
  data = datos
)

summary(modelo2)
confint(modelo2)

Estrés = β0 + β1Tiempo + β2Transbordos + β3Seguridad + β4Cuidado + ε

Interpretación condicional. Cada pendiente representa la diferencia esperada en estrés asociada con un aumento de una unidad en esa variable, manteniendo constantes las demás variables incluidas en el modelo.
Actividad 15.
  1. Interpreta tiempo_viaje: dirección, magnitud, unidad y condición de control.
  2. Interpreta transbordos de la misma forma.
  3. Interpreta seguridad. Recuerda que un punto adicional significa mayor percepción de seguridad.
  4. Interpreta cuidado como una comparación entre quienes tienen responsabilidades de cuidado (1) y quienes no (0).
  5. Para cada coeficiente, distingue su magnitud de su significancia estadística.
  6. Interpreta el intercepto del modelo múltiple. ¿Describe una combinación plausible de valores?
Importante. “Mantener constante” es una interpretación estadística de la comparación que hace el modelo. No significa que el estudio haya manipulado o fijado físicamente esas variables.

16. Comparar los dos modelos

# Resumen compacto para construir la tabla
comparacion <- tibble(
  modelo = c("Simple", "Múltiple"),
  beta_tiempo = c(
    coef(modelo1)["tiempo_viaje"],
    coef(modelo2)["tiempo_viaje"]
  ),
  p_tiempo = c(
    summary(modelo1)$coefficients["tiempo_viaje", "Pr(>|t|)"],
    summary(modelo2)$coefficients["tiempo_viaje", "Pr(>|t|)"]
  ),
  r2 = c(
    summary(modelo1)$r.squared,
    summary(modelo2)$r.squared
  ),
  r2_ajustado = c(
    summary(modelo1)$adj.r.squared,
    summary(modelo2)$adj.r.squared
  )
)

comparacion
ElementoModelo simpleModelo múltiple
Coeficiente de tiempo_viaje
p-value de tiempo_viaje
R2
R2 ajustado
Actividad 16.
  1. Completa la tabla con un número razonable de decimales.
  2. ¿Cambió el coeficiente de tiempo de viaje? ¿Qué nos sugiere ese cambio?
  3. ¿Aumentó R2? ¿Por qué al agregar variables R2 casi nunca disminuye?
  4. ¿Qué penalización introduce R2 ajustado y por qué puede ser útil?
  5. ¿Cuál modelo preferirías para describir el estrés en esta muestra? Justifica usando ajuste, interpretación y parsimonia.
  6. ¿El modelo múltiple demuestra causalidad? Explica por qué incluir controles ayuda, pero no resuelve por sí solo el problema causal.

Comparación formal opcional

Como el modelo simple está contenido dentro del múltiple, puedes comparar si el conjunto de variables adicionales mejora el ajuste:

anova(modelo1, modelo2)

Interpreta esta prueba como una comparación conjunta de los términos añadidos; no reemplaza la discusión conceptual sobre qué variables deberían incluirse.

17. Integración y comunicación final

17.1 Explica la regresión sin jerga

Reto de 150 palabras. Imagina que una persona que nunca ha tomado estadística pregunta: “¿Qué hiciste con esa regresión?”. Explica qué intentábamos comprender, qué hace la recta, qué significa su inclinación, por qué los puntos no caen exactamente sobre ella y qué aprendimos.

17.2 Responde la pregunta de investigación

Conclusión de máximo 200 palabras. Responde: “¿Cómo se relaciona el tiempo diario de desplazamiento con el estrés de los estudiantes?”. Incluye:
  • dirección y magnitud de la asociación;
  • p-value e intervalo de confianza;
  • R2 del modelo simple;
  • cambio entre el modelo simple y el múltiple;
  • una evaluación breve de los supuestos;
  • una advertencia explícita sobre causalidad.
No copies el output: selecciona la evidencia relevante y conviértela en un argumento comprensible.

17.3 Autoevaluación

Glosario mínimo

Valor observadoValor de estrés registrado para una persona.
Valor predichoValor de estrés que la recta estima para esa persona.
ResiduoObservado menos predicho; la parte no capturada por la recta para un caso.
InterceptoPredicción de Y cuando todas las X valen cero.
PendienteCambio esperado en Y por una unidad adicional de X.
p-valueCompatibilidad de los datos con la hipótesis nula, bajo el modelo y sus supuestos.
Intervalo de confianzaRango de valores plausibles para el parámetro según el procedimiento estadístico.
R2Proporción de variabilidad de Y explicada por el modelo en la muestra.