Preparación para el Examen Práctico — TC2001B.601

Autor/a

Jorge Juvenal Campos Ferreira

Fecha de publicación

16 de abril de 2026

Acerca de este documento

Este documento contiene las respuestas a los ejercicios propuestos para la preparación del examen práctico del curso TC2001B.601 — Introducción a la Ciencia de Datos (Ene-Jun 2026). Todas las bases de datos se leen directamente desde internet para garantizar reproducibilidad.

1 Preparación del entorno

Cargamos las librerías necesarias. Todas las llamadas a library() se concentran al inicio.

Código
library(tidyverse)   # Manipulación + visualización
library(scales)      # Formatos de números para las gráficas
library(plotly)      # Gráficas interactivas (Ejercicio 1)
library(ggpubr)      # ggbackground() para plantilla INEGI (Ejercicio 6)
library(knitr)       # Tablas con kable()

2 Ejercicio 1 — Evolución de búsquedas de ChatGPT en México

Enunciado
  1. Elabore una gráfica de líneas en la cual pueda ver la evolución de las búsquedas en Google de ChatGPT en México. Los datos están en este enlace. La columna semana muestra la fecha del domingo con el que inicia cada semana; chat_gpt_mexico es el índice de búsqueda (0 a 100).
  2. Determine la semana en la cual se alcanzó el día con mayor búsquedas de ChatGPT.
  3. ¿En qué fechas se alcanzan los mínimos locales y qué información aporta?

2.1 Carga de datos y gráfica base

Código
chatgpt <- read_csv("https://raw.githubusercontent.com/JuveCampos/TC2001B.601-Ciencia-de-datos-ene-jun-2026/refs/heads/main/05_EXAMENES/preparacion_examen_practico/chatgpt.csv") %>%
  filter(chat_gpt_mexico > 0) # Eliminamos los datos de cuando no existía ChatGPT

# Gráfica base de líneas con la evolución de las búsquedas
grafica_chatgpt <- chatgpt %>%
  ggplot(aes(x = semana, y = chat_gpt_mexico)) +
  geom_line(color = "#1e4c7d", linewidth = 0.7) +
  geom_point(color = "#1e4c7d", size = 0.8) +
  scale_x_date(date_breaks = "3 weeks", date_labels = "%Y-%m-%d") +
  labs(
    title    = "Evolución de búsquedas de ChatGPT en México",
    subtitle = "Índice de búsqueda semanal (0 = mínimo, 100 = máximo histórico)",
    x        = "Semana (fecha del domingo)",
    y        = "Índice de búsqueda",
    caption  = "Fuente: Google Trends"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5))

grafica_chatgpt

2.2 Semana con el máximo de búsquedas

Código
semana_max <- chatgpt %>%
  filter(chat_gpt_mexico == max(chat_gpt_mexico, na.rm = TRUE))

semana_max %>% kable()
semana chat_gpt_mexico
2025-09-28 100
2025-10-19 100

Respuesta. Las dos semanas en las que se alcanzó el valor máximo (100) fueron la del 28 de septiembre de 2025 y la del 19 de octubre de 2025.

2.3 Identificación de mínimos locales (gráfica interactiva)

Código
ggplotly(grafica_chatgpt)

Pase el cursor sobre cada punto para ver su fecha y valor.

Interpretación. Al inspeccionar los mínimos locales en la gráfica interactiva se observa que los picos hacia abajo tienden a caer en semanas que coinciden con:

  • Diciembre (vacaciones de fin de año / Navidad).
  • Semana Santa (marzo-abril).
  • Periodos vacacionales de verano (julio).

Esto sugiere que las búsquedas de ChatGPT están asociadas con actividad escolar y laboral: cuando la gente está de vacaciones, baja el interés.


3 Ejercicio 2 — Crecimiento sexenal del PIB

Enunciado

El archivo crecimiento_presidente.csv contiene la tasa de crecimiento acumulado para los primeros 23 trimestres de cada sexenio (hasta el 2024T2). Con estos datos, replique la gráfica original incluyendo todas las etiquetas y usando colores similares.

Código
crecimiento <- read_csv("https://raw.githubusercontent.com/JuveCampos/TC2001B.601-Ciencia-de-datos-ene-jun-2026/refs/heads/main/05_EXAMENES/preparacion_examen_practico/crecimiento_presidente.csv")

# Mapeo de colores de la paleta usada en la gráfica original
colores_presidente <- c(
  "verde oscuro" = "#2F4e43",
  "azul claro"   = "#97cce9",
  "café"         = "#98362e"
)

# Ordenamos a los presidentes en el orden cronológico (aparecen en el CSV)
crecimiento <- crecimiento %>%
  mutate(etiqueta = factor(etiqueta, levels = etiqueta))

# Replicamos la gráfica de barras
grafica_crecimiento <- crecimiento %>%
  ggplot(aes(x = etiqueta, y = crecimiento, fill = color)) +
  geom_col(width = 0.7) +
  geom_text(
    aes(label = paste0(crecimiento, "%")),
    vjust = -0.4, size = 4, fontface = "bold", family = "Ubuntu"
  ) +
  scale_fill_manual(values = colores_presidente, guide = "none") +
  scale_y_continuous(labels = scales::comma_format(suffix = "%"),
                     expand = expansion(mult = c(0, 0.1))) +
  labs(
    title    = "Crecimiento sexenal del PIB",
    subtitle = "Serie desestacionalizada y de tendencia ciclo.\nComparación primeros 23 trimestres de cada sexenio",
    x        = NULL,
    y        = NULL,
    caption  = "Elaborado por México, ¿Cómo vamos? con la serie desestacionalizada del PIB de INEGI"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title    = element_text(face = "bold", size = 20, color = "#6552d3"),
    plot.subtitle = element_text(color = "gray50"),
    panel.grid.major = element_blank(),
    axis.text.x   = element_text(face = "bold"),
    axis.line.x = element_line(),
    text = element_text(family = "Ubuntu")
  )

grafica_crecimiento

Interpretación. El sexenio de CSG tuvo el mayor crecimiento acumulado en los primeros 23 trimestres (24.8%), seguido por EZPDL (20.6%). Los sexenios más recientes (FCH, EPN y AMLO) tuvieron crecimientos considerablemente menores, siendo AMLO el de menor crecimiento acumulado (4.5%).


4 Ejercicio 3 — Métricas por vendedor

Enunciado

Con los datos de ventas_tienda.csv:

  1. Calcula por vendedor: número de transacciones, ingreso total e ingreso promedio por transacción.
  2. Construye un gráfico de barras ordenado por ingreso total (reorder() dentro del aes()).
  3. Añade geom_text() con etiqueta en formato numérico con separador de miles (prettyNum(x, big.mark = ",")).
  4. Aplica theme_minimal, título y caption con la fuente.

4.1 Cálculo de métricas

Código
ventas <- read_csv("https://raw.githubusercontent.com/JuveCampos/TC2001B.601-Ciencia-de-datos-ene-jun-2026/refs/heads/main/02_EJERCICIOS_PRACTICOS/Sesion%2002/archivos%20carga/Data/ventas_tienda.csv")

metricas_vendedor <- ventas %>%
  group_by(vendedor) %>%
  summarise(
    n_transacciones = n(), # Número de renglones
    ingreso_total   = sum(cantidad * precio_unitario, na.rm = TRUE),
    ingreso_prom    = ingreso_total / n_transacciones
  ) %>%
  arrange(desc(ingreso_total))

metricas_vendedor %>% kable(digits = 2)
vendedor n_transacciones ingreso_total ingreso_prom
Ana Garcia 5 5397.99 1079.60
Pedro Martinez 3 4029.96 1343.32
Maria Rodriguez 3 2096.00 698.67
Carlos Lopez 4 1507.28 376.82

4.2 Gráfico de barras

Código
grafica_vendedores <- metricas_vendedor %>%
  ggplot(aes(x = reorder(vendedor, -ingreso_total), y = ingreso_total)) +
  geom_col(fill = "#1e4c7d") +
  geom_text(
    aes(label = prettyNum(round(ingreso_total), big.mark = ",")),
    vjust = -0.4, size = 4
  ) +
  scale_y_continuous(
    labels = label_number(big.mark = ","),
    expand = expansion(mult = c(0, 0.12))
  ) +
  labs(
    title   = "Ingreso total por vendedor",
    x       = "Vendedor",
    y       = "Ingreso total",
    caption = "Fuente: Registros internos de ventas"
  ) +
  theme_minimal()

grafica_vendedores


5 Ejercicio 4 — Conversión de Celsius a Fahrenheit

Enunciado

Fórmula: \(°F = \left(\frac{9}{5} \cdot °C\right) + 32\).

  1. Genere una función propia que le permita realizar la transformación.
  2. Obtenga a cuántos grados Fahrenheit equivalen 40 °C.
Código
# (1) Función de conversión
celsius_a_fahrenheit <- function(celsius) {
  ((9 / 5) * celsius) + 32
}

# (2) Conversión de 40 °C
resultado_f <- celsius_a_fahrenheit(40)
print(str_c("40 °C equivalen a ", resultado_f, " °F"))
[1] "40 °C equivalen a 104 °F"

Respuesta. 40 grados Celsius equivalen a 104 °F (calorcito).


6 Ejercicio 5 — Tiempo de traslado

Enunciado

Encuesta de 40 trabajadores en CDMX con el tiempo de traslado en minutos. Datos en tiempo_traslado.csv.

  1. Cargar los datos.
  2. Calcular media, mediana, mínimo y máximo (con na.rm = TRUE).
  3. Identificar y manejar los NAs.
  4. Detectar outliers con el método IQR: reportar Q1, Q3, IQR, límites e IDs.
  5. Generar un boxplot.

6.1 Carga y estadísticas descriptivas

Código
traslado <- read_csv("https://raw.githubusercontent.com/JuveCampos/TC2001B.601-Ciencia-de-datos-ene-jun-2026/refs/heads/main/05_EXAMENES/preparacion_examen_practico/tiempo_traslado.csv")

estadisticas_traslado <- traslado %>%
  summarise(
    media   = mean(minutos, na.rm = TRUE),
    mediana = median(minutos, na.rm = TRUE),
    minimo  = min(minutos, na.rm = TRUE),
    maximo  = max(minutos, na.rm = TRUE)
  )

estadisticas_traslado %>% kable(digits = 2)
media mediana minimo maximo
43.68 36 2 180
Código
# También se puede calcular por fuera con las funciones clásicas
media_traslado   <- mean(traslado$minutos,   na.rm = TRUE)
mediana_traslado <- median(traslado$minutos, na.rm = TRUE)
min_traslado     <- min(traslado$minutos,    na.rm = TRUE)
max_traslado     <- max(traslado$minutos,    na.rm = TRUE)

Observación. El máximo (150 min) es mucho más grande que la media/mediana (~35–40 min), lo que sugiere la presencia de al menos un outlier alto. El mínimo (3 min) también parece muy pequeño para un traslado en CDMX (otro atípico, pero por abajo).

6.2 Manejo de NAs

Código
n_nas <- traslado %>%
  summarise(na_minutos = sum(is.na(minutos))) %>%
  pull(na_minutos)

print(paste0("Número de NAs en la columna minutos: ", n_nas))
[1] "Número de NAs en la columna minutos: 2"
Código
# Eliminamos los NAs para los cálculos posteriores (conservando IDs)
traslado_limpio <- traslado %>%
  filter(!is.na(minutos))

6.3 Detección de outliers con IQR

Código
q1   <- quantile(traslado_limpio$minutos, 0.25)
q3   <- quantile(traslado_limpio$minutos, 0.75)
iqr  <- q3 - q1
lim_inf <- q1 - 1.5 * iqr
lim_sup <- q3 + 1.5 * iqr

print(paste0("Q1 = ", q1, " | Q3 = ", q3, " | IQR = ", iqr))
[1] "Q1 = 31 | Q3 = 42 | IQR = 11"
Código
print(paste0("Límite inferior = ", lim_inf,
             " | Límite superior = ", lim_sup))
[1] "Límite inferior = 14.5 | Límite superior = 58.5"
Código
# Identificamos los IDs outliers (| representa "o" lógico)
outliers <- traslado_limpio %>%
  filter(minutos < lim_inf | minutos > lim_sup)

outliers %>% kable()
id minutos
2 3
7 150
16 2
20 180
37 3
40 155
Código
# Alternativa con between() negado
outliers <- traslado_limpio %>%
  filter(!between(minutos, lim_inf, lim_sup))

outliers %>% kable()
id minutos
2 3
7 150
16 2
20 180
37 3
40 155

Respuesta. Los outliers son las observaciones cuyo valor cae fuera de \([Q_1 - 1.5 \cdot IQR,\; Q_3 + 1.5 \cdot IQR]\). Los IDs correspondientes aparecen en la tabla anterior. Estos registros podrían ser errores de captura o casos genuinos extremos que merecen análisis aparte.

6.4 Boxplot

Código
traslado_limpio %>%
  ggplot(aes(y = minutos)) +
  geom_boxplot(fill = "#1e4c7d", alpha = 0.7, outlier.color = "red") +
  labs(
    title   = "Tiempo de traslado al trabajo (minutos)",
    y       = "Minutos",
    caption = "Fuente: Encuesta a 40 trabajadores en CDMX"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_blank(), axis.ticks.x = element_blank())


7 Ejercicio 6 — Inversión pública y privada como % del PIB

Enunciado

El archivo porcentaje_inversion_pib_4T.csv tiene los porcentajes de inversión pública y privada con respecto al PIB (datos INEGI). Replique la gráfica original usando la plantilla INEGI como fondo.

7.1 Construcción de la gráfica

Código
inversion <- read_csv("https://raw.githubusercontent.com/JuveCampos/TC2001B.601-Ciencia-de-datos-ene-jun-2026/refs/heads/main/05_EXAMENES/preparacion_examen_practico/porcentaje_inversion_pib_4T.csv")

# Pasamos a formato largo (tidy) para poder graficar con ggplot
inversion_long <- inversion %>%
  select(anio, `% Privada`, `% Pública`) %>%
  pivot_longer(
    cols      = c(`% Pública`, `% Privada`),
    names_to  = "tipo",
    values_to = "porcentaje"
  ) %>%
  mutate(
    tipo = factor(
      tipo,
      levels = c("% Privada", "% Pública"),
      labels = c("% Privada", "% Pública")
    )
  )

# Replicamos la gráfica con los colores de MCV
grafica_inversion <- inversion_long %>%
  ggplot(aes(x = anio, y = porcentaje, fill = tipo)) +
  geom_col() +
  geom_text(aes(label = str_c(porcentaje, "%")),
            color = "white", angle = 90,
            hjust = 1.1,
            position = position_stack(),
            family = "Ubuntu") +
  scale_fill_manual(values = c(
    "% Privada" = "#d75b99",
    "% Pública" = "#6552d4"
  )) +
  scale_x_continuous(breaks = 1993:2025) +
  scale_y_continuous(breaks = seq(0, 30, 5),
                     expand = expansion(c(0, 0.1)),
                     labels = scales::comma_format(suffix = "%")) +
  labs(
    title    = "Inversión como % del PIB",
    subtitle = "Como proporción del PIB - 4º trimestre de cada año",
    x        = NULL,
    y        = "Inversión como % del PIB",
    fill     = NULL,
    caption  = NULL
  ) +
  theme_minimal() +
  theme(
    legend.position = "bottom",
    plot.title      = element_text(face = "bold", color = "#6552d4", size = 20),
    plot.subtitle   = element_text(color = "gray50", size = 16),
    legend.text     = element_text(color = "gray50"),
    text            = element_text(family = "Ubuntu"),
    axis.text.x     = element_text(angle = 90, hjust = 1, vjust = 0.5),
    panel.grid.minor = element_blank(),
    plot.margin     = margin(t = 0.4, r = 0.4, b = 1.2, l = 0.4, unit = "cm"),
    panel.grid.major = element_blank()
  )

grafica_inversion

7.2 Gráfica sobre la plantilla INEGI

A continuación mostramos la versión final de la gráfica con la plantilla PDF de INEGI como fondo, usando ggpubr::ggbackground():

Código
# Guardamos con plantilla en la carpeta
plt_impresion <- ggbackground(
  gg = grafica_inversion,
  background = "../preparacion_examen_practico/01_inegi.pdf"
)

ggsave(filename = "grafica_inversion.png",
       plot = plt_impresion, device = "png",
       height = 6, width = 12)

Gráfica de barras apiladas mostrando la inversión pública y privada como porcentaje del PIB con la plantilla INEGI de fondo.

Gráfica final con la plantilla INEGI.

8 Ejercicio 7 — Rutas de entrega (Cuarteto de Anscombe)

Enunciado

Una empresa de logística tiene 4 rutas de entrega. Para cada ruta se registraron 11 observaciones con km y tiempo. Datos: rutas_entrega.csv.

  1. Calcula por ruta: media y desviación estándar de km y tiempo, y la correlación entre ambas. ¿Qué observas?
  2. Gráfico de dispersión km vs tiempo por ruta (facet_wrap) con línea de regresión en cada panel.
  3. Párrafo sobre la importancia de la visualización.

8.1 (a) Estadísticas descriptivas por ruta

Código
rutas <- read_csv("https://raw.githubusercontent.com/JuveCampos/TC2001B.601-Ciencia-de-datos-ene-jun-2026/refs/heads/main/05_EXAMENES/nuevos_ejercicios_propuestos/rutas_entrega.csv")

tabla_rutas <- rutas %>%
  group_by(ruta) %>%
  summarise(
    media_km      = mean(km),
    media_tiempo  = mean(tiempo),
    sd_km         = sd(km),
    sd_tiempo     = sd(tiempo),
    correlacion   = cor(km, tiempo)
  )

tabla_rutas %>% kable(digits = 3)
ruta media_km media_tiempo sd_km sd_tiempo correlacion
Ruta_A 9 7.501 3.317 2.032 0.816
Ruta_B 9 7.501 3.317 2.032 0.816
Ruta_C 9 7.500 3.317 2.030 0.816
Ruta_D 9 7.501 3.317 2.031 0.817

Observación. ¡Las medias, desviaciones estándar y correlaciones son prácticamente idénticas entre las 4 rutas! Este dataset corresponde al cuarteto de Anscombe (Anscombe, 1973): cuatro conjuntos de datos con estadísticas descriptivas casi iguales pero estructuras muy distintas. Lección: las estadísticas descriptivas nunca sustituyen a la visualización.

8.2 (b) Gráfico de dispersión por ruta

Código
grafica_rutas <- rutas %>%
  ggplot(aes(x = km, y = tiempo)) +
  geom_point(color = "#1e4c7d", size = 2) +
  geom_smooth(method = "lm", se = FALSE, color = "#C8102E") +
  facet_wrap(~ ruta) +
  labs(
    title    = "Relación entre kilómetros recorridos y tiempo de entrega",
    subtitle = "4 rutas de una empresa de logística (11 observaciones c/u)",
    x        = "Kilómetros",
    y        = "Tiempo (minutos)",
    caption  = "Fuente: Registros internos de la empresa"
  ) +
  theme_minimal()

grafica_rutas

8.3 (c) Importancia de la visualización

La visualización es crucial porque, aun cuando las cuatro rutas presentan estadísticas descriptivas (media, desviación estándar y correlación) prácticamente idénticas, la gráfica de dispersión revela que cada una tiene un patrón muy diferente: una muestra una relación lineal limpia, otra una curvatura, otra una línea con un outlier y otra un caso donde un solo punto extremo conduce toda la correlación. Si nos quedamos solo con los números, tomaríamos decisiones erróneas —por ejemplo, asumir que todas las rutas se comportan igual—. La gráfica nos permite ver la estructura real de los datos, detectar outliers y validar supuestos antes de ajustar modelos de regresión.


9 Ejercicio 8 — Dataset de salud

Enunciado

Dataset de 200 pacientes (salud.csv) con: edad, peso_kg, altura_cm, presion_sistolica, colesterol, horas_ejercicio_sem, glucosa.

  1. IDs con altura outlier (método IQR).
  2. Promedio de presion_sistolica, colesterol, horas_ejercicio_sem y glucosa por grupo de edad: jóvenes (≤29), adultos (30-60), mayores (61+).
  3. Gráfica de barras para cada variable, con el orden jóvenes → adultos → mayores.
  4. Dispersión presion_sistolica vs edad + correlación e interpretación.

9.1 (1) Outliers de altura

Código
salud <- read_csv("https://raw.githubusercontent.com/JuveCampos/TC2001B.601-Ciencia-de-datos-ene-jun-2026/refs/heads/main/05_EXAMENES/nuevos_ejercicios_propuestos/salud.csv")

q1_alt   <- quantile(salud$altura_cm, 0.25, na.rm = TRUE)
q3_alt   <- quantile(salud$altura_cm, 0.75, na.rm = TRUE)
iqr_alt  <- q3_alt - q1_alt
lim_inf_alt <- q1_alt - 1.5 * iqr_alt
lim_sup_alt <- q3_alt + 1.5 * iqr_alt

outliers_altura <- salud %>%
  filter(altura_cm < lim_inf_alt | altura_cm > lim_sup_alt) %>%
  select(paciente_id, altura_cm)

print(paste0("Q1=", q1_alt, " | Q3=", q3_alt, " | IQR=", iqr_alt))
[1] "Q1=158.375 | Q3=171.975 | IQR=13.6"
Código
print(paste0("Límites de altura: [", lim_inf_alt, ", ", lim_sup_alt, "]"))
[1] "Límites de altura: [137.975, 192.375]"
Código
outliers_altura %>% kable()
paciente_id altura_cm
25 197.3
147 134.8

Respuesta. Los IDs en la tabla outliers_altura corresponden a las personas cuya altura cae fuera del rango \([Q_1 - 1.5 \cdot IQR,\; Q_3 + 1.5 \cdot IQR]\).

9.2 (2) Promedios por grupo de edad

Código
salud_grupos <- salud %>%
  mutate(
    grupo_edad = case_when(
      edad <= 29 ~ "Jóvenes (<=29)",
      edad <= 60 ~ "Adultos (30-60)",
      TRUE       ~ "Mayores (61+)"
    ),
    # Aseguramos el orden: jóvenes, adultos, mayores
    grupo_edad = factor(
      grupo_edad,
      levels = c("Jóvenes (<=29)", "Adultos (30-60)", "Mayores (61+)")
    )
  )

promedios_grupo <- salud_grupos %>%
  group_by(grupo_edad) %>%
  summarise(
    presion_sistolica  = mean(presion_sistolica, na.rm = TRUE),
    colesterol         = mean(colesterol, na.rm = TRUE),
    horas_ejercicio    = mean(horas_ejercicio_sem, na.rm = TRUE),
    glucosa            = mean(glucosa, na.rm = TRUE)
  )

promedios_grupo %>% kable(digits = 2)
grupo_edad presion_sistolica colesterol horas_ejercicio glucosa
Jóvenes (<=29) 112.05 189.66 7.10 78.93
Adultos (30-60) 121.98 209.61 5.68 85.05
Mayores (61+) 134.44 220.78 4.05 95.57

9.3 (3) Gráficas de barras por variable (facetas)

Código
# Pasamos a formato largo para poder facetar
promedios_largo <- promedios_grupo %>%
  pivot_longer(
    cols      = -grupo_edad,
    names_to  = "variable",
    values_to = "promedio"
  ) %>%
  mutate(
    variable = recode(variable,
      presion_sistolica = "Presión sistólica",
      colesterol        = "Colesterol",
      horas_ejercicio   = "Horas ejercicio/sem",
      glucosa           = "Glucosa"
    )
  )

promedios_largo %>%
  ggplot(aes(x = grupo_edad, y = promedio, fill = grupo_edad)) +
  geom_col() +
  geom_text(aes(label = round(promedio, 1)),
            vjust = -0.4, size = 3.5) +
  facet_wrap(~ variable, scales = "free_y") +
  scale_fill_manual(values = c("#4FC3F7", "#1e4c7d", "#C8102E"),
                    guide = "none") +
  labs(
    title   = "Promedios de variables de salud por grupo de edad",
    x       = NULL,
    y       = "Promedio",
    caption = "Fuente: Dataset salud.csv (200 pacientes)"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 20, hjust = 1))

9.4 (4) Presión sistólica vs edad

Código
correlacion_pe <- cor(salud$presion_sistolica, salud$edad,
                      use = "complete.obs")

print(paste0("Correlación presión sistólica ~ edad: ",
             round(correlacion_pe, 3)))
[1] "Correlación presión sistólica ~ edad: 0.654"
Código
salud %>%
  ggplot(aes(x = edad, y = presion_sistolica)) +
  geom_point(color = "#1e4c7d", alpha = 0.6) +
  geom_smooth(method = "lm", se = TRUE, color = "#C8102E") +
  labs(
    title    = "Relación entre edad y presión sistólica",
    subtitle = paste0("Correlación de Pearson r = ",
                      round(correlacion_pe, 3)),
    x        = "Edad (años)",
    y        = "Presión sistólica (mmHg)",
    caption  = "Fuente: Dataset salud.csv"
  ) +
  theme_minimal()

Interpretación. La correlación es positiva y relativamente alta, lo que tiene sentido clínicamente: la presión sistólica tiende a aumentar con la edad. La gráfica de dispersión confirma este patrón —nube de puntos claramente ascendente y recta de regresión con pendiente positiva—, consistente con la literatura biomédica: el endurecimiento arterial progresivo con la edad eleva la presión sistólica.


10 Sesión

Código
R version 4.4.3 (2025-02-28)
Platform: aarch64-apple-darwin20
Running under: macOS 26.3

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib 
LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.0

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/Mexico_City
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] knitr_1.50      ggpubr_0.6.0    plotly_4.12.0   scales_1.4.0   
 [5] lubridate_1.9.4 forcats_1.0.0   stringr_1.6.0   dplyr_1.1.4    
 [9] purrr_1.2.0     readr_2.1.5     tidyr_1.3.1     tibble_3.3.1   
[13] ggplot2_4.0.2   tidyverse_2.0.0

loaded via a namespace (and not attached):
 [1] gtable_0.3.6       xfun_0.52          htmlwidgets_1.6.4  rstatix_0.7.2     
 [5] lattice_0.22-6     tzdb_0.5.0         vctrs_0.6.5        tools_4.4.3       
 [9] crosstalk_1.2.1    generics_0.1.4     curl_7.0.0         parallel_4.4.3    
[13] pkgconfig_2.0.3    Matrix_1.7-2       data.table_1.17.8  RColorBrewer_1.1-3
[17] S7_0.2.0           lifecycle_1.0.4    compiler_4.4.3     farver_2.1.2      
[21] carData_3.0-5      htmltools_0.5.8.1  yaml_2.3.10        lazyeval_0.2.2    
[25] Formula_1.2-5      pillar_1.11.1      car_3.1-3          crayon_1.5.3      
[29] abind_1.4-8        nlme_3.1-167       tidyselect_1.2.1   digest_0.6.37     
[33] stringi_1.8.7      splines_4.4.3      labeling_0.4.3     fastmap_1.2.0     
[37] grid_4.4.3         cli_3.6.5          magrittr_2.0.4     broom_1.0.10      
[41] withr_3.0.2        backports_1.5.0    bit64_4.6.0-1      timechange_0.3.0  
[45] rmarkdown_2.29     httr_1.4.7         bit_4.6.0          ggsignif_0.6.4    
[49] hms_1.1.3          evaluate_1.0.4     viridisLite_0.4.2  mgcv_1.9-1        
[53] rlang_1.1.6        glue_1.8.0         rstudioapi_0.17.1  vroom_1.6.5       
[57] jsonlite_2.0.0     R6_2.6.1