1) Carga y preparación de datos

En esta sección se cargan los datos y se realizan transformaciones previas para asegurar que todas las columnas tengan el tipo correcto y nombres utilizables en código.

# Librerías necesarias
library(tidyverse)   # ggplot2, dplyr, readr, tidyr, etc.
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ ggplot2   4.0.0     ✔ tibble    3.3.0
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.2.0     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(janitor)     # clean_names()
## 
## Attaching package: 'janitor'
## 
## The following objects are masked from 'package:stats':
## 
##     chisq.test, fisher.test
library(lubridate)   # manejo de fechas
library(readr)       # lectura rápida de CSV
# Ruta del archivo
ruta <- "/Users/Pilar/Desktop/CURSO R/S5_ASA_estadisticasPasajeros.csv"

# 1) Lectura
pasajeros <- read_csv(ruta, show_col_types = FALSE)

# 2) Normalización de nombres para evitar espacios/acentos
pasajeros <- pasajeros %>% clean_names()

# 3) Reparación de columna de mes:
#    En el archivo viene como "anio_mes" (o similar). Crearemos:
#    - anio: año (numérico)
#    - mes: mes (numérico 1..12)
# Intentamos detectar una columna que represente "anio mes"
posibles_nombres <- names(pasajeros)
cand <- posibles_nombres[grepl("anio.*mes|año.*mes|anio_mes|ano_mes|anomes|year.*month|y_m|ym", posibles_nombres)]
if (length(cand) == 0) {
  warning
} else {
  col_anio_mes <- cand[1]
  # Intento robusto de parseo: ymd/ym y distintos separadores
  anio_mes_chr <- pasajeros[[col_anio_mes]] %>% as.character()
  # Reemplazar separadores comunes
  anio_mes_chr2 <- gsub("[/_\\.]", "-", anio_mes_chr)
  anio_mes_chr2 <- gsub("\\s+", "-", anio_mes_chr2)
  # Intentar como "YYYY-MM" (ym) o "YYYY-MM-DD" (ymd)
  fecha_try <- suppressWarnings(ym(anio_mes_chr2))
  if (all(is.na(fecha_try))) {
    fecha_try <- suppressWarnings(ymd(anio_mes_chr2))
  }
  # Si aún hay NA, último intento con parse_date_time
  if (all(is.na(fecha_try))) {
    fecha_try <- suppressWarnings(parse_date_time(anio_mes_chr2, orders = c("Y-m", "Y/m", "Ym", "Y m", "Y-m-d", "Ymd", "Y m d")))
  }
  pasajeros <- pasajeros %>%
    mutate(
      anio = year(fecha_try),
      mes  = month(fecha_try)
    )
}

# 4) Estandarizar nombres típicos de columnas de pasajeros si existen con variaciones
pos_nac <- posibles_nombres[grepl("nacional", posibles_nombres, ignore.case = TRUE)]
pos_int <- posibles_nombres[grepl("internacional", posibles_nombres, ignore.case = TRUE)]
if (length(pos_nac) > 0) {
  pasajeros <- pasajeros %>% rename(pasajeros_nacionales = !!sym(pos_nac[1]))
}
if (length(pos_int) > 0) {
  pasajeros <- pasajeros %>% rename(pasajeros_internacionales = !!sym(pos_int[1]))
}

# 5) Si existen estado/aeropuerto con nombres distintos, normalizarlos
if ("estado" %in% names(pasajeros) == FALSE) {
  cand_estado <- posibles_nombres[grepl("estado|entidad|state", posibles_nombres, ignore.case = TRUE)]
  if (length(cand_estado) > 0) pasajeros <- pasajeros %>% rename(estado = !!sym(cand_estado[1]))
}
if ("aeropuerto" %in% names(pasajeros) == FALSE) {
  cand_aerop <- posibles_nombres[grepl("aerop|iata|airport", posibles_nombres, ignore.case = TRUE)]
  if (length(cand_aerop) > 0) pasajeros <- pasajeros %>% rename(aeropuerto = !!sym(cand_aerop[1]))
}

# 6) Crear total de pasajeros por registro (si hay ambas columnas)
if (all(c("pasajeros_nacionales", "pasajeros_internacionales") %in% names(pasajeros))) {
  pasajeros <- pasajeros %>%
    mutate(total_pasajeros = pasajeros_nacionales + pasajeros_internacionales)
}

# Vista rápida
glimpse(pasajeros)
## Rows: 216
## Columns: 9
## $ anio_mes                  <dbl> 201501, 201501, 201501, 201501, 201501, 2015…
## $ aeropuerto                <chr> "CEN", "CLQ", "CME", "CPE", "CTM", "CVM", "G…
## $ descripcion               <chr> "Ciudad Obregon", "Colima", "Ciudad del Carm…
## $ estado                    <chr> "Sonora", "Colima", "Campeche", "Campeche", …
## $ pasajeros_nacionales      <dbl> 17149, 8486, 56079, 13264, 13153, 4695, 1315…
## $ pasajeros_internacionales <dbl> 721, 124, 3126, 215, 0, 139, 386, 2684, 61, …
## $ anio                      <dbl> 2015, 2015, 2015, 2015, 2015, 2015, 2015, 20…
## $ mes                       <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
## $ total_pasajeros           <dbl> 17870, 8610, 59205, 13479, 13153, 4834, 1701…

Nota Al normalizar los nombres de columnas se evita que espacios, acentos o mayúsculas provoquen errores de sintaxis en el código posterior.


2) Estructura y resúmenes

str(pasajeros)
## tibble [216 × 9] (S3: tbl_df/tbl/data.frame)
##  $ anio_mes                 : num [1:216] 201501 201501 201501 201501 201501 ...
##  $ aeropuerto               : chr [1:216] "CEN" "CLQ" "CME" "CPE" ...
##  $ descripcion              : chr [1:216] "Ciudad Obregon" "Colima" "Ciudad del Carmen" "Campeche" ...
##  $ estado                   : chr [1:216] "Sonora" "Colima" "Campeche" "Campeche" ...
##  $ pasajeros_nacionales     : num [1:216] 17149 8486 56079 13264 13153 ...
##  $ pasajeros_internacionales: num [1:216] 721 124 3126 215 0 ...
##  $ anio                     : num [1:216] 2015 2015 2015 2015 2015 ...
##  $ mes                      : num [1:216] 1 1 1 1 1 1 1 1 1 1 ...
##  $ total_pasajeros          : num [1:216] 17870 8610 59205 13479 13153 ...
summary(select(pasajeros, where(is.numeric)))
##     anio_mes      pasajeros_nacionales pasajeros_internacionales      anio     
##  Min.   :201501   Min.   :   63        Min.   :   0.0            Min.   :2015  
##  1st Qu.:201504   1st Qu.: 1198        1st Qu.:   7.0            1st Qu.:2015  
##  Median :201506   Median : 7947        Median : 107.0            Median :2015  
##  Mean   :201506   Mean   :10608        Mean   : 818.2            Mean   :2015  
##  3rd Qu.:201509   3rd Qu.:14884        3rd Qu.: 584.0            3rd Qu.:2015  
##  Max.   :201512   Max.   :56418        Max.   :7042.0            Max.   :2015  
##       mes        total_pasajeros
##  Min.   : 1.00   Min.   :   63  
##  1st Qu.: 3.75   1st Qu.: 4463  
##  Median : 6.50   Median : 8264  
##  Mean   : 6.50   Mean   :11427  
##  3rd Qu.: 9.25   3rd Qu.:15079  
##  Max.   :12.00   Max.   :59205

Interpretación Estos resúmenes permiten comprobar rangos y detectar valores atípicos o faltantes antes de graficar.


3) Frecuencias de variables categóricas

# Frecuencias si existen las variables
if ("estado" %in% names(pasajeros)) print(table(pasajeros$estado))
## 
## Baja California  Sur             Campeche               Colima 
##                   12                   24                   12 
##            Michoacan              Nayarit               Oaxaca 
##                   12                   12                   12 
##               Puebla         Quintana Roo      San Luis Potosi 
##                   24                   12                   12 
##               Sonora           Tamaulipas             Veracruz 
##                   36                   36                   12
if ("aeropuerto" %in% names(pasajeros)) print(table(pasajeros$aeropuerto))
## 
## CEN CLQ CME CPE CTM CVM GYM LTO MAM NLD NOG PAZ PBC PXM TCN TPQ TSL UPN 
##  12  12  12  12  12  12  12  12  12  12  12  12  12  12  12  12  12  12
if ("mes" %in% names(pasajeros)) print(table(pasajeros$mes, useNA = "ifany"))
## 
##  1  2  3  4  5  6  7  8  9 10 11 12 
## 18 18 18 18 18 18 18 18 18 18 18 18

Interpretación La distribución de categorías ayuda a dimensionar la cobertura de estados y aeropuertos, y el balance temporal por mes.


4) Agregaciones de interés

# Total por estado
agg_estado <- pasajeros %>%
  filter(!is.na(estado)) %>%
  group_by(estado) %>%
  summarise(total = sum(total_pasajeros, na.rm = TRUE)) %>%
  arrange(desc(total))

# Promedio mensual (usando la columna 'mes' creada)
agg_mes <- pasajeros %>%
  filter(!is.na(mes)) %>%
  group_by(mes) %>%
  summarise(prom_nac = mean(pasajeros_nacionales, na.rm = TRUE),
            prom_int = mean(pasajeros_internacionales, na.rm = TRUE),
            prom_total = mean(total_pasajeros, na.rm = TRUE))

agg_estado
## # A tibble: 12 × 2
##    estado                total
##    <chr>                 <dbl>
##  1 Campeche             804905
##  2 Puebla               330623
##  3 Sonora               265364
##  4 Tamaulipas           245788
##  5 Oaxaca               185330
##  6 Quintana Roo         179377
##  7 Colima               113583
##  8 Nayarit              113043
##  9 Michoacan            110067
## 10 Veracruz              60575
## 11 Baja California  Sur  57907
## 12 San Luis Potosi        1598
agg_mes
## # A tibble: 12 × 4
##      mes prom_nac prom_int prom_total
##    <dbl>    <dbl>    <dbl>      <dbl>
##  1     1   10355.     779.     11133.
##  2     2    8970.     759.      9729.
##  3     3   10647.     880.     11527.
##  4     4   10251.     863.     11114.
##  5     5   10268.     853.     11121.
##  6     6   10243.     771.     11014.
##  7     7   11606.     795.     12402.
##  8     8   10885.     843.     11727.
##  9     9    9636.     679.     10315.
## 10    10   10681.     822.     11503.
## 11    11   11207.     890.     12097 
## 12    12   12552.     886.     13438.

Interpretación En general, los estados con áreas metropolitanas concentran mayor volumen anual, mientras que otros muestran variabilidad asociada a temporadas o eventos locales.


5) Gráficos descriptivos

5.1 Histograma de pasajeros (nacionales)

ggplot(pasajeros, aes(x = pasajeros_nacionales)) +
  geom_histogram(color = "white", bins = 30) +
  labs(title = "Distribución de pasajeros nacionales",
       x = "Pasajeros nacionales",
       y = "Frecuencia")

Interpretación La masa principal se concentra en valores bajos a medios; unos pocos puntos reflejan aeropuertos con alta afluencia.


5.2 Barras: total de pasajeros por estado

agg_estado %>%
  ggplot(aes(x = reorder(estado, -total), y = total)) +
  geom_bar(stat = "identity") +
  coord_flip() +
  labs(title = "Total de pasajeros por estado",
       x = "Estado",
       y = "Total anual de pasajeros")

Interpretación El liderazgo de ciertos estados refleja su peso demográfico y su centralidad como nodos de conexión.


5.3 Boxplot: dispersión por mes

ggplot(pasajeros, aes(x = factor(mes), y = pasajeros_nacionales)) +
  geom_boxplot() +
  labs(title = "Dispersión de pasajeros nacionales por mes",
       x = "Mes",
       y = "Pasajeros nacionales")

Interpretación Se aprecian meses con mayor dispersión, indicio de estacionalidad.


5.4 Numérica vs categórica (promedio por estado)

pasajeros %>%
  filter(!is.na(estado)) %>%
  group_by(estado) %>%
  summarise(prom_nac = mean(pasajeros_nacionales, na.rm = TRUE)) %>%
  ggplot(aes(x = reorder(estado, -prom_nac), y = prom_nac)) +
  geom_col() +
  coord_flip() +
  labs(title = "Promedio de pasajeros nacionales por estado",
       x = "Estado",
       y = "Promedio de pasajeros nacionales")

Interpretación Estados turísticos o industriales tienden a agrupar promedios más elevados.


5.5 Numérica vs numérica (nacionales vs internacionales)

ggplot(pasajeros, aes(x = pasajeros_nacionales, y = pasajeros_internacionales)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", se = FALSE) +
  labs(title = "Relación entre pasajeros nacionales e internacionales",
       x = "Pasajeros nacionales",
       y = "Pasajeros internacionales")
## `geom_smooth()` using formula = 'y ~ x'

Interpretación La relación positiva sugiere que los aeropuertos con demanda interna robusta suelen exhibir también mayor tráfico internacional.


6) Concluyendo

Este reporte muestra patrones descriptivos claros en 2015: concentración del tráfico en pocos estados, señales de estacionalidad por mes y una asociación directa entre el flujo nacional e internacional. Las transformaciones previas garantizan que los gráficos y tablas se generen sin errores de sintaxis asociados a nombres de columnas o formatos de fecha.