1) Carga de datos

# Cargar el CSV 
datos_csv <- read_csv("S5_ASA_estadisticasPasajeros.csv")
## Rows: 216 Columns: 6
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): Codigo IATA, Descripcion, Estado
## dbl (3): Anio mes, Pasajeros nacionales, Pasajeros internacionales
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Limpiar nombres de columnas y asignar a 'datos'
datos <- datos_csv %>% janitor::clean_names()

# Vista de las primeras filas
head(datos)
## # A tibble: 6 × 6
##   anio_mes codigo_iata descripcion       estado       pasajeros_nacionales
##      <dbl> <chr>       <chr>             <chr>                       <dbl>
## 1   201501 CEN         Ciudad Obregon    Sonora                      17149
## 2   201501 CLQ         Colima            Colima                       8486
## 3   201501 CME         Ciudad del Carmen Campeche                    56079
## 4   201501 CPE         Campeche          Campeche                    13264
## 5   201501 CTM         Chetumal          Quintana Roo                13153
## 6   201501 CVM         Ciudad Victoria   Tamaulipas                   4695
## # ℹ 1 more variable: pasajeros_internacionales <dbl>

2) Verificación de estructura y tipos

# Comprobaciones básicas
if (!exists("datos")) stop("El objeto 'datos' no existe. Asegúrate de haber corrido el bloque de carga.")
if (!is.data.frame(datos)) stop("'datos' no es un data frame")
if (ncol(datos) == 0) stop("'datos' no tiene columnas")

# Arreglar nombres vacíos o duplicados
names(datos) <- make.names(names(datos), unique = TRUE)

# Estructura dataframe
str(datos)
## spc_tbl_ [216 × 6] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ anio_mes                 : num [1:216] 201501 201501 201501 201501 201501 ...
##  $ codigo_iata              : 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 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   `Anio mes` = col_double(),
##   ..   `Codigo IATA` = col_character(),
##   ..   Descripcion = col_character(),
##   ..   Estado = col_character(),
##   ..   `Pasajeros nacionales` = col_double(),
##   ..   `Pasajeros internacionales` = col_double()
##   .. )
##  - attr(*, "problems")=<externalptr>
# Resumen de NA y tipos
na_resumen <- data.frame(
  variable = names(datos),
  tipo     = sapply(datos, function(x) class(x)[1]),
  na       = sapply(datos, function(x) sum(is.na(x))),
  na_prop  = sapply(datos, function(x) mean(is.na(x))),
  check.names = FALSE
)

knitr::kable(na_resumen, caption = "NA por variable")
NA por variable
variable tipo na na_prop
anio_mes anio_mes numeric 0 0
codigo_iata codigo_iata character 0 0
descripcion descripcion character 0 0
estado estado character 0 0
pasajeros_nacionales pasajeros_nacionales numeric 0 0
pasajeros_internacionales pasajeros_internacionales numeric 0 0

3) Resúmenes numéricos

numericas <- names(datos)[vapply(datos, is.numeric, TRUE)]

if (length(numericas) == 0) {
  cat("**No se detectaron variables numéricas.**\n")
} else {
  resumen_num <- datos %>%
    dplyr::summarise(
      dplyr::across(
        dplyr::all_of(numericas),
        list(
          min     = ~ min(.x, na.rm = TRUE),
          q1      = ~ quantile(.x, 0.25, na.rm = TRUE),
          media   = ~ mean(.x, na.rm = TRUE),
          mediana = ~ median(.x, na.rm = TRUE),
          q3      = ~ quantile(.x, 0.75, na.rm = TRUE),
          max     = ~ max(.x, na.rm = TRUE),
          na      = ~ sum(is.na(.x))
        ),
        .names = "{.col}_{.fn}"
      )
    )

  knitr::kable(resumen_num, caption = "Resumen numérico por variable")
}
Resumen numérico por variable
anio_mes_min anio_mes_q1 anio_mes_media anio_mes_mediana anio_mes_q3 anio_mes_max anio_mes_na pasajeros_nacionales_min pasajeros_nacionales_q1 pasajeros_nacionales_media pasajeros_nacionales_mediana pasajeros_nacionales_q3 pasajeros_nacionales_max pasajeros_nacionales_na pasajeros_internacionales_min pasajeros_internacionales_q1 pasajeros_internacionales_media pasajeros_internacionales_mediana pasajeros_internacionales_q3 pasajeros_internacionales_max pasajeros_internacionales_na
201501 201503.8 201506.5 201506.5 201509.2 201512 0 63 1198.5 10608.42 7947 14883.75 56418 0 0 7 818.2454 107 584 7042 0

4) Tablas de frecuencia (categóricas)

categoricas <- names(datos)[map_lgl(datos, ~ is.character(.x) || is.factor(.x))]
if (length(categoricas) == 0) {
  cat("**No se detectaron variables categóricas.**\n")
} else {
  top_cats <- head(categoricas, 8)
  for (v in top_cats) {
    cat("\n## Frecuencia de:", v, "\n")
    print(datos %>% count(!!sym(v), sort = TRUE) %>% mutate(prop = n/sum(n)) %>% kable())
  }
}
## 
## ## Frecuencia de: codigo_iata 
## 
## 
## |codigo_iata |  n|      prop|
## |:-----------|--:|---------:|
## |CEN         | 12| 0.0555556|
## |CLQ         | 12| 0.0555556|
## |CME         | 12| 0.0555556|
## |CPE         | 12| 0.0555556|
## |CTM         | 12| 0.0555556|
## |CVM         | 12| 0.0555556|
## |GYM         | 12| 0.0555556|
## |LTO         | 12| 0.0555556|
## |MAM         | 12| 0.0555556|
## |NLD         | 12| 0.0555556|
## |NOG         | 12| 0.0555556|
## |PAZ         | 12| 0.0555556|
## |PBC         | 12| 0.0555556|
## |PXM         | 12| 0.0555556|
## |TCN         | 12| 0.0555556|
## |TPQ         | 12| 0.0555556|
## |TSL         | 12| 0.0555556|
## |UPN         | 12| 0.0555556|
## 
## ## Frecuencia de: descripcion 
## 
## 
## |descripcion       |  n|      prop|
## |:-----------------|--:|---------:|
## |Campeche          | 12| 0.0555556|
## |Chetumal          | 12| 0.0555556|
## |Ciudad Obregon    | 12| 0.0555556|
## |Ciudad Victoria   | 12| 0.0555556|
## |Ciudad del Carmen | 12| 0.0555556|
## |Colima            | 12| 0.0555556|
## |Guaymas           | 12| 0.0555556|
## |Loreto            | 12| 0.0555556|
## |Matamoros         | 12| 0.0555556|
## |Nogales           | 12| 0.0555556|
## |Nuevo Laredo      | 12| 0.0555556|
## |Poza Rica         | 12| 0.0555556|
## |Puebla            | 12| 0.0555556|
## |Puerto Escondido  | 12| 0.0555556|
## |Tamuin            | 12| 0.0555556|
## |Tehuacan          | 12| 0.0555556|
## |Tepic             | 12| 0.0555556|
## |Uruapan           | 12| 0.0555556|
## 
## ## Frecuencia de: estado 
## 
## 
## |estado               |  n|      prop|
## |:--------------------|--:|---------:|
## |Sonora               | 36| 0.1666667|
## |Tamaulipas           | 36| 0.1666667|
## |Campeche             | 24| 0.1111111|
## |Puebla               | 24| 0.1111111|
## |Baja California  Sur | 12| 0.0555556|
## |Colima               | 12| 0.0555556|
## |Michoacan            | 12| 0.0555556|
## |Nayarit              | 12| 0.0555556|
## |Oaxaca               | 12| 0.0555556|
## |Quintana Roo         | 12| 0.0555556|
## |San Luis Potosi      | 12| 0.0555556|
## |Veracruz             | 12| 0.0555556|

5) Agregaciones interesantes

safe_pick <- function(x) {
  x <- unique(x[!is.na(x) & nzchar(x)])
  if (length(x) >= 1) x[1] else NULL
}

nms <- names(datos)

# Candidatas por patrón
col_estado_cand     <- nms[grepl("estado|entidad",   nms, ignore.case = TRUE)]
col_aeropuerto_cand <- nms[grepl("aerop|aeropuerto|airport|terminal", nms, ignore.case = TRUE)]
col_pasajeros_cand  <- nms[grepl("pasaj|passenger|pasenger|total",    nms, ignore.case = TRUE)]

col_estado     <- safe_pick(col_estado_cand)
col_aeropuerto <- safe_pick(col_aeropuerto_cand)
col_pasajeros  <- safe_pick(col_pasajeros_cand)

# Intentar construir "total_pasajeros" si no se detectó
cols_nac <- nms[grepl("nac", nms, ignore.case = TRUE)]
# Evitar confundir "int" con "intervalo" o similares
cols_int_all <- nms[grepl("int", nms, ignore.case = TRUE)]
cols_int     <- setdiff(cols_int_all, nms[grepl("interval", nms, ignore.case = TRUE)])

if (is.null(col_pasajeros) && length(cols_nac) >= 1 && length(cols_int) >= 1) {
  col_pasajeros <- "total_pasajeros_tmp"
  datos <- datos %>%
    dplyr::mutate(
      total_pasajeros_tmp = dplyr::coalesce(.data[[cols_nac[1]]], 0) + dplyr::coalesce(.data[[cols_int[1]]], 0)
    )
}

list(
  detectado_estado     = col_estado,
  detectado_aeropuerto = col_aeropuerto,
  detectado_pasajeros  = col_pasajeros
)
## $detectado_estado
## [1] "estado"
## 
## $detectado_aeropuerto
## NULL
## 
## $detectado_pasajeros
## [1] "pasajeros_nacionales"
if (!is.null(col_estado) && !is.null(col_pasajeros)) {
  agg_estado <- datos %>% group_by(!!sym(col_estado)) %>%
    summarise(total_pasajeros = sum(!!sym(col_pasajeros), na.rm = TRUE), .groups = "drop") %>%
    arrange(desc(total_pasajeros))
  kable(head(agg_estado, 20), caption = "Top estados por total de pasajeros")
}
Top estados por total de pasajeros
estado total_pasajeros
Campeche 769864
Puebla 267567
Sonora 253788
Tamaulipas 243126
Oaxaca 181706
Quintana Roo 179259
Nayarit 113043
Colima 112656
Michoacan 95635
Veracruz 60575
Baja California Sur 12602
San Luis Potosi 1598
if (!is.null(col_aeropuerto) && !is.null(col_pasajeros)) {
  agg_aer <- datos %>% group_by(!!sym(col_aeropuerto)) %>%
    summarise(total_pasajeros = sum(!!sym(col_pasajeros), na.rm = TRUE), .groups = "drop") %>%
    arrange(desc(total_pasajeros))
  kable(head(agg_aer, 20), caption = "Top aeropuertos por total de pasajeros")
}

6) Gráficos descriptivos

6.1 Histograma

col_nac <- names(datos) %>% keep(~ str_detect(.x, regex("nac", ignore_case = TRUE))) %>% first()
col_int <- names(datos) %>% keep(~ str_detect(.x, regex("int", ignore_case = TRUE))) %>% first()
col_hist <- coalesce(col_nac, col_int, if (length(numericas)>0) numericas[1] else NA_character_)

if (!is.na(col_hist)) {
  ggplot(datos, aes(x = .data[[col_hist]])) +
    geom_histogram(bins = 30, fill = "skyblue") +
    labs(x = col_hist, y = "Frecuencia", title = paste("Histograma de", col_hist))
}

6.2 Barras por estado o aeropuerto

if (!is.null(col_estado) && !is.null(col_pasajeros)) {
  top_est <- datos %>% group_by(!!sym(col_estado)) %>% summarise(total = sum(!!sym(col_pasajeros), na.rm=TRUE), .groups="drop") %>% arrange(desc(total)) %>% slice_head(n=15)
  ggplot(top_est, aes(x = reorder(.data[[col_estado]], total), y = total)) +
    geom_col(fill = "steelblue") +
    coord_flip() +
    labs(x = "Estado", y = "Total de pasajeros", title = "Top 15 estados por total de pasajeros")
}

6.3 Boxplot por mes

if ("mes" %in% names(datos) && !is.null(col_pasajeros)) {
  ggplot(datos, aes(x = as.factor(mes), y = .data[[col_pasajeros]])) +
    geom_boxplot(fill = "orange", alpha = 0.6) +
    labs(x = "Mes", y = "Pasajeros", title = "Dispersión de pasajeros por mes")
}

6.4 Numérica vs categórica

if (length(numericas) >= 1 && length(categoricas) >= 1) {
  vnum <- numericas[1]
  vcat <- categoricas[1]
  datos %>% group_by(.data[[vcat]]) %>% summarise(prom = mean(.data[[vnum]], na.rm=TRUE), .groups="drop") %>%
    slice_max(order_by = prom, n = 20) %>%
    ggplot(aes(x = reorder(.data[[vcat]], prom), y = prom)) +
    geom_col(fill = "purple") +
    coord_flip() +
    labs(x = vcat, y = paste("Promedio de", vnum), title = paste("Promedio de", vnum, "por", vcat))
}

6.5 Numérica vs numérica

if (length(numericas) >= 2) {
  v1 <- numericas[1]; v2 <- numericas[2]
  ggplot(datos, aes(x = .data[[v1]], y = .data[[v2]])) +
    geom_point(alpha = 0.6, color = "darkgreen") +
    geom_smooth(method = "lm", se = FALSE, color = "red") +
    labs(x = v1, y = v2, title = paste("Relación entre", v1, "y", v2))
}
## `geom_smooth()` using formula = 'y ~ x'

7) Conclusión