Clase 7

Author

Rubén Cool

¿Cómo es la interfaz de Rstudio?

La interfaz de RStudio consta de varios elementos básicos:

  • Consola: Es donde se ejecutan los comandos de R y se muestra la salida.

  • Editor de Script: Permite escribir y editar scripts de R. Ideal para desarrollar código de manera organizada.

  • Entorno de Trabajo y Historial: Muestra las variables y archivos en uso, junto con el historial de comandos.

  • Explorador de Archivos y Directorios: Facilita la navegación y gestión de archivos.

  • Gráficos, Paquetes y Ayuda: Paneles para visualizar gráficos, cargar paquetes y acceder a la documentación.

  • Terminal: Proporciona acceso a una terminal de línea de comandos.

  • Pestañas de Archivo: Permite abrir múltiples scripts o documentos al mismo tiempo.

  • Barra de Herramientas: Contiene botones para funciones comunes, como guardar, cargar y ejecutar.

  • Barra de Menú: Ofrece acceso a configuraciones y opciones adicionales.

Estos elementos hacen que RStudio sea una herramienta eficiente y versátil para trabajar con R y otros lenguajes de programación.

Preparación y Exploración de Datos

Caso de estudio sobre Autos

La siguiente base de datos cars describe los registros empíricos de 50 pruebas de conducción realizadas para evaluar el rendimiento de frenado en automóviles. La base contiene dos variables clave:

  • speed: La velocidad a la que viajaba el vehículo justo antes de accionar el freno (medida en millas por hora).

  • dist: La distancia total requerida para detener el vehículo por completo (medida en pies).

Para este análisis, usaremos el conjunto de datos integrado `cars`, que relaciona la velocidad de un automóvil (`speed` en mph) y la distancia de frenado (`dist` en pies).

Cargar la librería para gráficos (recuerda instalarla antes si no la tienes con install.packages(“ggplot2”)). Primero, cargamos la librería para graficar.

library(ggplot2)
Warning: package 'ggplot2' was built under R version 4.6.1

Antes de modelar, siempre visualiza los datos para detectar tendencias o anomalías.

# Primeras filas de los datos
head(cars)
  speed dist
1     4    2
2     4   10
3     7    4
4     7   22
5     8   16
6     9   10
# Diagrama de dispersión usando ggplot2
ggplot(data = cars, aes(x = speed, y = dist)) +
  geom_point(color = "steelblue", size = 3) +
  theme_minimal() +
  labs(
    title = "Relación entre Velocidad y Distancia de Frenado",
    x = "Velocidad (mph)",
    y = "Distancia de frenado (pies)"
  )

¿La relación parece lineal? ¿A medida que aumenta la velocidad, qué pasa con la distancia?

Ajuste del Modelo Lineal

Ahora le pedimos a R que encuentre la “línea de mejor ajuste” utilizando el método de Mínimos Cuadrados Ordinarios. Usamos la función lm() (Linear Model).

La sintaxis siempre es: lm(variable_respuesta ~ variable_explicativa, data = datos).

# Ajustamos el modelo y lo guardamos en un objeto llamado 'modelo_coches'
#library(stats) Cargar la librería para hacer el ajuste
modelo_coches <- lm(dist ~ speed, data = cars)

R no muestra nada por defecto al guardar, necesitamos pedirle un resumen. Extraemos los resultados con la función summary()

summary(modelo_coches)

Call:
lm(formula = dist ~ speed, data = cars)

Residuals:
    Min      1Q  Median      3Q     Max 
-29.069  -9.525  -2.272   9.215  43.201 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) -17.5791     6.7584  -2.601   0.0123 *  
speed         3.9324     0.4155   9.464 1.49e-12 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 15.38 on 48 degrees of freedom
Multiple R-squared:  0.6511,    Adjusted R-squared:  0.6438 
F-statistic: 89.57 on 1 and 48 DF,  p-value: 1.49e-12

Lectura para el output:

  1. Estimate (Coeficientes):

    • (Intercept): El valor \(\hat{E}(Y)\) cuando \(X = 0\). (Nota: A veces no tiene sentido físico, ¿un auto a 0 mph frena en -17 pies?).

    • speed: La estimación de la pendiente (\(\beta_1\)). Por cada milla por hora extra de velocidad, la estimación de la distancia de frenado promedio aumenta 3.93 pies

  2. Std. Error: el error Estándar de los coeficientes.

    • (Intercept): $$SE(\hat{\beta}_0) = \sqrt{MS_{Res}\left( \frac{1}{n} + \frac{\bar{x}^2}{S_{xx}}\right) }$$

    • speed: $$SE(\hat{\beta}_1) = \sqrt{\frac{MS_{Res} }{S_{xx}}}$$

      Noten que si el denominador es muy grande (es decir, si medimos la velocidad en un rango muy amplio de datos, desde autos muy lentos hasta muy rápidos), el Error Estándar de \(\hat{\beta}_1\) disminuye. ¡A mayor dispersión en \(X\), mayor precisión en la pendiente!

  3. Pr(>|t|) (P-valor): Indica si la variable es estadísticamente significativa. Al ser menor a 0.05 (tiene estrellitas ***).

Prueba de significacia del Modelo

  1. Contraste de Hipótesis

    \(H_0: \beta_1=0 \hspace{0.5cm} vs. \hspace{0.5cm} \beta_1 \neq0\)

  2. Estadístico de prueba

    \(t_0=9.46\)

  3. P-valor

    \(1.49 \cdot 10^{-12}\)

Decisión: Con una significancia de \(\alpha=0.05\) se rechaza la hipótesis a favor de la alternativa, es decir, los datos sugieren que la velocidad sí explica la distancia de frenado de forma lineal.

Prueba de significacia para el intercepto

  1. Contraste de Hipótesis

    \(H_0: \beta_0=0 \hspace{0.5cm} vs. \hspace{0.5cm} \beta_0 \neq0\)

  2. Estadístico de prueba

    \(t_0=-2.601\)

  3. P-valor

    \(0.0123\)

Decisión: Con una significancia de \(\alpha=0.05\) se rechaza la hipótesis a favor de la alternativa, es decir, los datos sugieren que \(\beta_0\neq0\). En este caso, no se tiene interpretación ya que no tiene sentido físico que cuando \(x=0\) el la estimación del frenado promedio sea \(-17.57\).

Modelo ajustado

\(\hat{y}=-17.57+3.93x\)

Regresamos a ggplot2 para sobreponer la recta de regresión que acabamos de calcular sobre nuestros datos originales.

ggplot(data = cars, aes(x = speed, y = dist)) +
  geom_point(color = "steelblue", size = 3) +
  # geom_smooth con method="lm" grafica automáticamente la recta de regresión
  geom_smooth(method = "lm", color = "darkred", se = FALSE) + 
  theme_minimal() +
  labs(
    title = "Modelo de Regresión Lineal Simple",
    subtitle = paste("Distancia =", round(coef(modelo_coches)[1], 2), "+", 
                     round(coef(modelo_coches)[2], 2), "* Velocidad"),
    x = "Velocidad (mph)",
    y = "Distancia de frenado (pies)"
  )
`geom_smooth()` using formula = 'y ~ x'

Nota

  1. Al momento de escribir la fórmula en `lm()`, es común cometer el error de escribir `lm(speed ~ dist)`.
  2. El intercepto negativo (-17.579) en este ejemplo siempre genera ruido. Los modelos lineales a veces solo son válidos dentro del rango de datos observados (interpolación vs. extrapolación).

Caso de estudio sobre Pingüinos

Se analizarán datos sobre pingüinos adultos pertenecientes a diferentes especies presentes en islas del archipiélago Palmer (Antártida), que incluyen su tamaño (longitud de la aleta, masa corporal, dimensiones del pico) y sexo.

Se necesita la librería ‘data.table’ para poder hacer la lectura de la base de datos. Asegúrate que la base de datos “pinguinos.csv” esté localizada en la misma carpeta que tu script de RStudio, de lo contrario podría generarte problemas. Además verifica que tu directorio esté localizado en la misma carpeta de tu script.

Session > Set Working Directory > Choose Directory (Eliges la carpeta donde está localizado tu script). Nota: No guardarlo en el OneDrive/Nube.

library(data.table)
Warning: package 'data.table' was built under R version 4.6.1

Adjuntando el paquete: 'data.table'
The following object is masked from 'package:base':

    %notin%
datos_pinguinos<-fread("pinguinos.csv")
head(datos_pinguinos)
   species    island bill_len bill_dep flipper_len body_mass    sex  year
    <char>    <char>    <num>    <num>       <int>     <int> <char> <int>
1:  Adelie Torgersen     39.1     18.7         181      3750   male  2007
2:  Adelie Torgersen     39.5     17.4         186      3800 female  2007
3:  Adelie Torgersen     40.3     18.0         195      3250 female  2007
4:  Adelie Torgersen       NA       NA          NA        NA   <NA>  2007
5:  Adelie Torgersen     36.7     19.3         193      3450 female  2007
6:  Adelie Torgersen     39.3     20.6         190      3650   male  2007
# Diagrama de dispersión usando ggplot2
ggplot(data = datos_pinguinos, aes(x = bill_len, y = body_mass)) +
  geom_point(color = "steelblue", size = 3) +
  theme_minimal() +
  labs(
    title = "Relación entre longitud de pico y Peso",
    x = "Longitud del pico (milimetros)",
    y = "Masa corporal (gramos)"
  )
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_point()`).

¿La relación parece lineal? ¿A medida que aumenta la longitud del pico, qué pasa con la masa corporal?

# Ajustamos el modelo y lo guardamos en un objeto llamado 'modelo_pinguinos'
#library(stats) Cargar la librería para hacer el ajuste
modelo_pinguinos <- lm(body_mass ~ bill_len, data = datos_pinguinos)
summary(modelo_pinguinos)

Call:
lm(formula = body_mass ~ bill_len, data = datos_pinguinos)

Residuals:
     Min       1Q   Median       3Q      Max 
-1132.82  -294.51   -44.67   248.91  1036.52 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 2685.439    217.478  12.348  < 2e-16 ***
bill_len      24.464      5.146   4.754 3.63e-06 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 416.1 on 217 degrees of freedom
  (1 observation deleted due to missingness)
Multiple R-squared:  0.09434,   Adjusted R-squared:  0.09017 
F-statistic:  22.6 on 1 and 217 DF,  p-value: 3.625e-06

Modelo ajustado

\(\hat{y}=2685.43+24.46x\)

Regresamos a ggplot2 para sobreponer la recta de regresión que acabamos de calcular sobre nuestros datos originales.

ggplot(data = datos_pinguinos, aes(x = bill_len, y = body_mass)) +
  geom_point(color = "steelblue", size = 3) +
  # geom_smooth con method="lm" grafica automáticamente la recta de regresión
  geom_smooth(method = "lm", color = "darkred", se = FALSE) + 
  theme_minimal() +
  labs(
    title = "Modelo de Regresión Lineal Simple",
    subtitle = paste("Masa corporal =", round(coef(modelo_pinguinos)[1], 2), "+", 
                     round(coef(modelo_pinguinos)[2], 2), "* Longitud del pico"),
    x = "Longitud de pico (mm)",
    y = "Masa corporal (g)"
  )
`geom_smooth()` using formula = 'y ~ x'
Warning: Removed 1 row containing non-finite outside the scale range
(`stat_smooth()`).
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_point()`).

Análisis Exploratorio

ggplot(datos_pinguinos, aes(x = bill_len, y = body_mass, color = species)) +
  geom_point() +
   # method = "lm" agrega la línea de regresión
  labs(
    title = "Masa vs Longitud del Pico",
    subtitle = "Adelie vs Chinstrap",
    x = "Longitud del Pico",
    y = "Masa Corporal",
    color = "Especie"
  ) +
  theme_minimal()  # Opcional: le da un fondo más limpio
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_point()`).

Caso de estudio sobre

Se analizarán los datos de Pesos del corazón y del cuerpo de muestras de gatos machos y hembras utilizados en experimentos con digital. Todos los gatos eran adultos y pesaban más de 2 kg.

library(MASS)
datos_gatos<-cats
head(datos_gatos)
  Sex Bwt Hwt
1   F 2.0 7.0
2   F 2.0 7.4
3   F 2.0 9.5
4   F 2.1 7.2
5   F 2.1 7.3
6   F 2.1 7.6
# Diagrama de dispersión usando ggplot2
ggplot(data = datos_gatos, aes(x = Bwt, y = Hwt)) +
  geom_point(color = "steelblue", size = 3) +
  theme_minimal() +
  labs(
    title = "Relación entre peso del cuerpo y Peso del corazón",
    x = "Peso del gato (Kg)",
    y = "Peso del corazón (g)"
  )

¿La relación parece lineal? ¿A medida que aumenta el peso del gato, qué pasa con el peso del corazón?

# Ajustamos el modelo y lo guardamos en un objeto llamado 'modelo_pinguinos'
#library(stats) Cargar la librería para hacer el ajuste
modelo_gato <- lm(Hwt ~ Bwt, data = datos_gatos)
summary(modelo_gato)

Call:
lm(formula = Hwt ~ Bwt, data = datos_gatos)

Residuals:
    Min      1Q  Median      3Q     Max 
-3.5694 -0.9634 -0.0921  1.0426  5.1238 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  -0.3567     0.6923  -0.515    0.607    
Bwt           4.0341     0.2503  16.119   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 1.452 on 142 degrees of freedom
Multiple R-squared:  0.6466,    Adjusted R-squared:  0.6441 
F-statistic: 259.8 on 1 and 142 DF,  p-value: < 2.2e-16

Modelo ajustado

\(\hat{y}=-0.3567+4.03x\)

Regresamos a ggplot2 para sobreponer la recta de regresión que acabamos de calcular sobre nuestros datos originales.

ggplot(data = datos_gatos, aes(x = Bwt, y = Hwt)) +
  geom_point(color = "steelblue", size = 3) +
  # geom_smooth con method="lm" grafica automáticamente la recta de regresión
  geom_smooth(method = "lm", color = "darkred", se = FALSE) + 
  theme_minimal() +
  labs(
    title = "Modelo de Regresión Lineal Simple",
    subtitle = paste("Peso del corazón gato =", round(coef(modelo_gato)[1], 2), "+", 
                     round(coef(modelo_gato)[2], 2), "* Peso del gato"),
    x = "Peso del gato (Kg)",
    y = "Peso del corazón (g)"
  )
`geom_smooth()` using formula = 'y ~ x'

Prueba de significacia del Modelo

  1. Contraste de Hipótesis

    \(H_0: \beta_1=0 \hspace{0.5cm} vs. \hspace{0.5cm} \beta_1 \neq0\)

  2. Estadístico de prueba

    \(t_0=16.119\)

  3. P-valor

    \(2 \cdot 10^{-16}\)

Decisión: Con una significancia de \(\alpha=0.05\) se rechaza la hipótesis a favor de la alternativa, es decir, los datos sugieren que la el peso de los gatos sí explica el peso de su corazón.

Prueba de significacia para el intercepto

  1. Contraste de Hipótesis

    \(H_0: \beta_0=0 \hspace{0.5cm} vs. \hspace{0.5cm} \beta_0 \neq0\)

  2. Estadístico de prueba

    \(t_0=-0.515\)

  3. P-valor

    \(0.607\)

Decisión: Con una significancia de \(\alpha=0.05\) no se rechaza la hipótesis a favor de la alternativa, es decir, no existe evidencia suficiente para decir que no se cumple \(\beta_0=0\). En este caso, se elimina \(\beta_0\) del modelo, por lo que el modelo de regresión tiene la siguiente forma:

\[y=\beta_1+\epsilon\]

Se procede a realizar un nuevo ajuste de este modelo.

modelo_gato2 <- lm(Hwt ~ Bwt-1, data = datos_gatos)
summary(modelo_gato2)

Call:
lm(formula = Hwt ~ Bwt - 1, data = datos_gatos)

Residuals:
    Min      1Q  Median      3Q     Max 
-3.4563 -0.9980 -0.1003  1.0044  5.2623 

Coefficients:
    Estimate Std. Error t value Pr(>|t|)    
Bwt  3.90711    0.04364   89.53   <2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 1.449 on 143 degrees of freedom
Multiple R-squared:  0.9825,    Adjusted R-squared:  0.9823 
F-statistic:  8015 on 1 and 143 DF,  p-value: < 2.2e-16

Modelo ajustado

\(\hat{y}=3.907x\)

ggplot(data = datos_gatos, aes(x = Bwt, y = Hwt)) +
  geom_point(color = "steelblue", size = 3) +
  # Agregamos formula = y ~ x - 1 para forzar la recta por el origen
  geom_smooth(method = "lm", formula = y ~ x - 1, color = "darkred", se = FALSE) + 
  theme_minimal() +
  labs(
    title = "Modelo de Regresión Lineal Simple (Sin Intercepto)",
    # Corregimos el paste y cambiamos a coef()[1] porque ya no hay intercepto
    subtitle = paste("Peso del corazón =", 
                     round(coef(modelo_gato2)[1], 2), "* Peso del gato"),
    x = "Peso del gato (Kg)",
    y = "Peso del corazón (g)"
  )

ggplot(data = datos_gatos, aes(x = Bwt, y = Hwt)) +
  # 1. Capa de puntos (los datos reales)
  geom_point(color = "gray50", size = 2, alpha = 0.7) +
  
  # 2. Capa del modelo CON intercepto (línea azul punteada)
  geom_smooth(method = "lm", formula = y ~ x, 
              color = "blue", linetype = "dashed", se = FALSE) + 
  
  # 3. Capa del modelo SIN intercepto (línea roja sólida)
  geom_smooth(method = "lm", formula = y ~ x - 1, 
              color = "darkred", linetype = "solid", se = FALSE) + 
  
  theme_minimal() +
  labs(
    title = "Comparación de Modelos: Masa Cardíaca Felina",
    # Usamos paste0 y \n para poner las dos ecuaciones en el subtítulo (una en cada línea)
    subtitle = paste0(
      "Azul (Con Int.): Peso = ", round(coef(modelo_gato)[1], 2), " + ", round(coef(modelo_gato)[2], 2), " * Peso gato\n",
      "Roja (Sin Int.): Peso = ", round(coef(modelo_gato2)[1], 2), " * Peso gato"
    ),
    x = "Peso del gato (Kg)",
    y = "Peso del corazón (g)"
  ) + coord_cartesian(xlim = c(0, 4), ylim = c(0, 20))