Datos
Lo primero que imaigné cuando pensé en un mapa con lines son las
rutas aereas en Argentina. Por supuesto encontrar esos datos no fue una
tarea fácil. No porque no hubiera datos, al contrario encontré mucha
información sobre pasajeros, rutas, vuelos, etc. Algunos en tablas
publicadas en formato pdf. Otras tables en excel, una debajo de la otra
en la misma hoja sin mucha explicación de que era cada cosa. En algunos
casos eran datos derivados de fuentes oficiales, pero sin enformación
sobre cómo habían sido procesados para llegar a tener la pinta que
tenían.
Finalmente me decidí por los datos de Aterrizajes
y despegues procesados por ANAC en el año 2023 que si bien tiene
datos de vuelos individuales, puedo extraer la información de las rutas
aereas activas y que empresas las usan.
vuelos <- fread("https://datos.transporte.gob.ar/dataset/21038a1a-c3c7-4494-b76a-3a2a8fbb83b5/resource/e910fead-ade3-40ce-ae8f-cad2017aa007/download/202309_informe_ministerio.csv") %>%
janitor::clean_names()
rutas <- vuelos %>%
.[clasificacion_vuelo == "Doméstico" &
clase_de_vuelo_todos_los_vuelos == "Regular" &
tipo_de_movimiento == "Despegue"] %>%
setnames("origen_destino", "destino") %>%
.[, ruta := paste0(aeropuerto, "-", destino)] %>%
.[, .(ruta = unique(ruta)), by = .(aerolinea_nombre)] %>%
tidyr::separate(ruta, into = c("origen", "destino"), remove = FALSE) %>%
setDT() %>%
.[, ruta_inv := paste0(destino, "-", origen)]
rutas_unicas <- c()
for (r in seq_len(nrow(rutas))) {
if (!(rutas$ruta[r] %in% rutas_unicas) & !(rutas$ruta_inv[r] %in% rutas_unicas)) {
rutas_unicas <- c(rutas_unicas, rutas$ruta[r])
}
}
rutas <- rutas[data.table(ruta = rutas_unicas), on = .NATURAL] %>%
.[aerolinea_nombre %in% c("AEROLINEAS ARGENTINAS SA", "FB LÍNEAS AÉREAS - FLYBONDI", "JETSMART AIRLINES S.A.")] %>%
.[, id_ruta := seq_len(.N)]
Todo muy ingenuo de mi parte, me llevo mucho más tiempo del que
imaginaba poder quedarme con las rutas únicas. El problema es que
“IGU-EZE” es lo mismo que “EZE-IGU” para este problema en particular.
Pero finalmente y con un poco de fuerza bruta lo logré. También me quedo
con las empresas principales, ya que hay muchas empresas privada con
poquisimos vuelos que solo suman ruido.
A mitad de camino me di cuenta que como esto se llama 30 días de
MAPAS necesito también la ubicación geográfica de los aeropuertos para
graficarlos y conectarlos según las rutas. El Ministerio de Transporte
tenía los dtos publicados, el único detalle es que la columna latitud en
ese dataset es en realidad la longitud. No hay remate.
ubicación_aeropuertos <- fread("https://datos.transporte.gob.ar/dataset/62b3fe5f-ffe6-4d8f-9d59-bfabe75d1ee8/resource/eb54e49e-9a5a-4614-91f4-526c650d0105/download/aeropuertos_detalle.csv") %>%
.[, .(local, latitud = longitud, longitud = latitud)]
mapa <- rnaturalearth::ne_countries(country = c("Argentina", "Falkland Islands"), returnclass = "sf")
origen <- ubicación_aeropuertos[rutas, on = c("local" = "origen")] %>%
setnames(c("local"), c("aeropuerto")) %>%
.[, destino := NULL]
destino <- ubicación_aeropuertos[rutas, on = c("local" = "destino")] %>%
setnames(c("local"), c("aeropuerto")) %>%
.[, origen := NULL]
Finalmente, con el mapa, las rutas y la ubicación de los aeropuertos
logré el gráfico que quería. Para graficar las rutas la clave está en
agregar la columna id_ruta
que luego sirve para graficar
lineas por cada uno de esos grupos que se forman con el aeropuerto de
origen y el de destino.
rbind(origen, destino) %>%
.[, aerolinea_nombre := forcats::fct_recode(aerolinea_nombre,
"Aerolineas Argentinas" = "AEROLINEAS ARGENTINAS SA",
"Flybondi" = "FB LÍNEAS AÉREAS - FLYBONDI",
"JetSmart" = "JETSMART AIRLINES S.A.")] %>%
ggplot(aes(longitud, latitud)) +
geom_sf(data = mapa, inherit.aes = FALSE, fill = "grey98") +
geom_point(data = ~copy(.x)[, aerolinea_nombre := NULL], color = "grey80", alpha = 0.5, size = 1) +
geom_line(data = ~copy(.x)[, aerolinea_nombre := NULL], aes(group = id_ruta),
color = "grey80", alpha = 0.5) +
geom_point(aes(color = aerolinea_nombre), alpha = 0.5, size = 1) +
geom_line(aes(color = aerolinea_nombre, group = id_ruta),
position = position_dodge(width = 0.5)) +
scale_color_manual(values = c("#346EA3", "#FFBF34", "#AA1C2A"), guide = NULL) +
facet_wrap(~aerolinea_nombre) +
labs(x = NULL, y = NULL, color = NULL,
title = "Rutas aéreas en Argentina",
subtitle = "El mercado está dominado por AA con 190 rutas",
caption = "Fuente: Administración Nacional de Aviación Civil") +
theme_minimal(base_size = 10,
base_family = "Roboto Condensed Light") +
theme(plot.title.position = "plot",
plot.title = element_text(face = "bold"))
# ggsave("day2.png", device = png, type = "cairo", bg = "white", width = 25, height = 18, units = "cm", dpi = 150)
LS0tCnRpdGxlOiAnRGlhIDI6IExpbmVhcycKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldCgKCWVjaG8gPSBUUlVFLAoJbWVzc2FnZSA9IEZBTFNFLAoJd2FybmluZyA9IEZBTFNFCikKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRhdGEudGFibGUpCmBgYAoKIyMgRGF0b3MKCkxvIHByaW1lcm8gcXVlIGltYWlnbsOpIGN1YW5kbyBwZW5zw6kgZW4gdW4gbWFwYSBjb24gbGluZXMgc29uIGxhcyBydXRhcyBhZXJlYXMgZW4gQXJnZW50aW5hLiBQb3Igc3VwdWVzdG8gZW5jb250cmFyIGVzb3MgZGF0b3Mgbm8gZnVlIHVuYSB0YXJlYSBmw6FjaWwuIE5vIHBvcnF1ZSBubyBodWJpZXJhIGRhdG9zLCBhbCBjb250cmFyaW8gZW5jb250csOpIG11Y2hhIGluZm9ybWFjacOzbiBzb2JyZSBwYXNhamVyb3MsIHJ1dGFzLCB2dWVsb3MsIGV0Yy4gQWxndW5vcyBlbiB0YWJsYXMgcHVibGljYWRhcyBlbiBmb3JtYXRvIHBkZi4gT3RyYXMgdGFibGVzIGVuIGV4Y2VsLCB1bmEgZGViYWpvIGRlIGxhIG90cmEgZW4gbGEgbWlzbWEgaG9qYSBzaW4gbXVjaGEgZXhwbGljYWNpw7NuIGRlIHF1ZSBlcmEgY2FkYSBjb3NhLiBFbiBhbGd1bm9zIGNhc29zIGVyYW4gZGF0b3MgZGVyaXZhZG9zIGRlIGZ1ZW50ZXMgb2ZpY2lhbGVzLCBwZXJvIHNpbiBlbmZvcm1hY2nDs24gc29icmUgY8OzbW8gaGFiw61hbiBzaWRvIHByb2Nlc2Fkb3MgcGFyYSBsbGVnYXIgYSB0ZW5lciBsYSBwaW50YSBxdWUgdGVuw61hbi4KCkZpbmFsbWVudGUgbWUgZGVjaWTDrSBwb3IgbG9zIGRhdG9zIGRlIFtBdGVycml6YWplcyB5IGRlc3BlZ3VlcyBwcm9jZXNhZG9zIHBvciBBTkFDIGVuIGVsIGHDsW8gMjAyM10oaHR0cHM6Ly9kYXRvcy50cmFuc3BvcnRlLmdvYi5hci9kYXRhc2V0L2F0ZXJyaXphamVzLXktZGVzcGVndWVzLXByb2Nlc2Fkb3MtcG9yLWxhLWFkbWluaXN0cmFjaW9uLW5hY2lvbmFsLWRlLWF2aWFjaW9uLWNpdmlsLWFuYWMvYXJjaGl2by9lOTEwZmVhZC1hZGUzLTQwY2UtYWU4Zi1jYWQyMDE3YWEwMDcpIHF1ZSBzaSBiaWVuIHRpZW5lIGRhdG9zIGRlIHZ1ZWxvcyBpbmRpdmlkdWFsZXMsIHB1ZWRvIGV4dHJhZXIgbGEgaW5mb3JtYWNpw7NuIGRlIGxhcyBydXRhcyBhZXJlYXMgYWN0aXZhcyB5IHF1ZSBlbXByZXNhcyBsYXMgdXNhbi4KCmBgYHtyfQp2dWVsb3MgPC0gZnJlYWQoImh0dHBzOi8vZGF0b3MudHJhbnNwb3J0ZS5nb2IuYXIvZGF0YXNldC8yMTAzOGExYS1jM2M3LTQ0OTQtYjc2YS0zYTJhOGZiYjgzYjUvcmVzb3VyY2UvZTkxMGZlYWQtYWRlMy00MGNlLWFlOGYtY2FkMjAxN2FhMDA3L2Rvd25sb2FkLzIwMjMwOV9pbmZvcm1lX21pbmlzdGVyaW8uY3N2IikgJT4lIAogIGphbml0b3I6OmNsZWFuX25hbWVzKCkKCnJ1dGFzIDwtIHZ1ZWxvcyAlPiUgCiAgLltjbGFzaWZpY2FjaW9uX3Z1ZWxvID09ICJEb23DqXN0aWNvIiAmIAogICAgICBjbGFzZV9kZV92dWVsb190b2Rvc19sb3NfdnVlbG9zID09ICJSZWd1bGFyIiAmIAogICAgICB0aXBvX2RlX21vdmltaWVudG8gPT0gIkRlc3BlZ3VlIl0gJT4lIAogIHNldG5hbWVzKCJvcmlnZW5fZGVzdGlubyIsICJkZXN0aW5vIikgJT4lIAogIC5bLCBydXRhIDo9IHBhc3RlMChhZXJvcHVlcnRvLCAiLSIsIGRlc3Rpbm8pXSAlPiUgCiAgLlssIC4ocnV0YSA9IHVuaXF1ZShydXRhKSksIGJ5ID0gLihhZXJvbGluZWFfbm9tYnJlKV0gJT4lIAogIHRpZHlyOjpzZXBhcmF0ZShydXRhLCBpbnRvID0gYygib3JpZ2VuIiwgImRlc3Rpbm8iKSwgcmVtb3ZlID0gRkFMU0UpICU+JSAKICBzZXREVCgpICU+JSAKICAuWywgcnV0YV9pbnYgOj0gcGFzdGUwKGRlc3Rpbm8sICItIiwgb3JpZ2VuKV0gCgpydXRhc191bmljYXMgPC0gYygpCgpmb3IgKHIgaW4gc2VxX2xlbihucm93KHJ1dGFzKSkpIHsKICAKICBpZiAoIShydXRhcyRydXRhW3JdICVpbiUgcnV0YXNfdW5pY2FzKSAmICEocnV0YXMkcnV0YV9pbnZbcl0gJWluJSBydXRhc191bmljYXMpKSB7CiAgICBydXRhc191bmljYXMgPC0gYyhydXRhc191bmljYXMsIHJ1dGFzJHJ1dGFbcl0pCiAgICAKICB9CiAgCn0KCnJ1dGFzIDwtIHJ1dGFzW2RhdGEudGFibGUocnV0YSA9IHJ1dGFzX3VuaWNhcyksIG9uID0gLk5BVFVSQUxdICU+JSAKICAuW2Flcm9saW5lYV9ub21icmUgJWluJSBjKCJBRVJPTElORUFTIEFSR0VOVElOQVMgU0EiLCAiRkIgTMONTkVBUyBBw4lSRUFTIC0gRkxZQk9OREkiLCAiSkVUU01BUlQgQUlSTElORVMgUy5BLiIpXSAlPiUgCiAgLlssIGlkX3J1dGEgOj0gc2VxX2xlbiguTildCmBgYAoKVG9kbyBtdXkgaW5nZW51byBkZSBtaSBwYXJ0ZSwgbWUgbGxldm8gbXVjaG8gbcOhcyB0aWVtcG8gZGVsIHF1ZSBpbWFnaW5hYmEgcG9kZXIgcXVlZGFybWUgY29uIGxhcyBydXRhcyDDum5pY2FzLiBFbCBwcm9ibGVtYSBlcyBxdWUgIklHVS1FWkUiIGVzIGxvIG1pc21vIHF1ZSAiRVpFLUlHVSIgcGFyYSBlc3RlIHByb2JsZW1hIGVuIHBhcnRpY3VsYXIuIFBlcm8gZmluYWxtZW50ZSB5IGNvbiB1biBwb2NvIGRlIGZ1ZXJ6YSBicnV0YSBsbyBsb2dyw6kuIFRhbWJpw6luIG1lIHF1ZWRvIGNvbiBsYXMgZW1wcmVzYXMgcHJpbmNpcGFsZXMsIHlhIHF1ZSBoYXkgbXVjaGFzIGVtcHJlc2FzIHByaXZhZGEgY29uIHBvcXVpc2ltb3MgdnVlbG9zIHF1ZSBzb2xvIHN1bWFuIHJ1aWRvLgoKQSBtaXRhZCBkZSBjYW1pbm8gbWUgZGkgY3VlbnRhIHF1ZSBjb21vIGVzdG8gc2UgbGxhbWEgMzAgZMOtYXMgZGUgTUFQQVMgbmVjZXNpdG8gdGFtYmnDqW4gbGEgdWJpY2FjacOzbiBnZW9ncsOhZmljYSBkZSBsb3MgYWVyb3B1ZXJ0b3MgcGFyYSBncmFmaWNhcmxvcyB5IGNvbmVjdGFybG9zIHNlZ8O6biBsYXMgcnV0YXMuIEVsIE1pbmlzdGVyaW8gZGUgVHJhbnNwb3J0ZSB0ZW7DrWEgbG9zIGR0b3MgcHVibGljYWRvcywgZWwgw7puaWNvIGRldGFsbGUgZXMgcXVlIGxhIGNvbHVtbmEgbGF0aXR1ZCBlbiBlc2UgZGF0YXNldCBlcyBlbiByZWFsaWRhZCBsYSBsb25naXR1ZC4gTm8gaGF5IHJlbWF0ZS4KCjxpZnJhbWUgc3JjPSJodHRwczovL21hc3RvZG9uLnNvY2lhbC9AZWxpb2NhbXAvMTExMzA5NzEzNzEwNTk4Mjg5L2VtYmVkIiB3aWR0aD0iNDAwIiBoZWlnaHQ9IjUwMCIgYWxsb3dmdWxsc2NyZWVuPSJhbGxvd2Z1bGxzY3JlZW4iIHNhbmRib3g9ImFsbG93LXNjcmlwdHMgYWxsb3ctc2FtZS1vcmlnaW4gYWxsb3ctcG9wdXBzIGFsbG93LXBvcHVwcy10by1lc2NhcGUtc2FuZGJveCBhbGxvdy1mb3JtcyI+PC9pZnJhbWU+CgpgYGB7cn0KdWJpY2FjacOzbl9hZXJvcHVlcnRvcyA8LSBmcmVhZCgiaHR0cHM6Ly9kYXRvcy50cmFuc3BvcnRlLmdvYi5hci9kYXRhc2V0LzYyYjNmZTVmLWZmZTYtNGQ4Zi05ZDU5LWJmYWJlNzVkMWVlOC9yZXNvdXJjZS9lYjU0ZTQ5ZS05YTVhLTQ2MTQtOTFmNC01MjZjNjUwZDAxMDUvZG93bmxvYWQvYWVyb3B1ZXJ0b3NfZGV0YWxsZS5jc3YiKSAlPiUgCiAgLlssIC4obG9jYWwsIGxhdGl0dWQgPSBsb25naXR1ZCwgbG9uZ2l0dWQgPSBsYXRpdHVkKV0KCm1hcGEgPC0gcm5hdHVyYWxlYXJ0aDo6bmVfY291bnRyaWVzKGNvdW50cnkgPSBjKCJBcmdlbnRpbmEiLCAiRmFsa2xhbmQgSXNsYW5kcyIpLCByZXR1cm5jbGFzcyA9ICJzZiIpCgpvcmlnZW4gPC0gdWJpY2FjacOzbl9hZXJvcHVlcnRvc1tydXRhcywgb24gPSBjKCJsb2NhbCIgPSAib3JpZ2VuIildICU+JSAKICBzZXRuYW1lcyhjKCJsb2NhbCIpLCBjKCJhZXJvcHVlcnRvIikpICU+JSAKICAuWywgZGVzdGlubyA6PSBOVUxMXQoKZGVzdGlubyA8LSB1YmljYWNpw7NuX2Flcm9wdWVydG9zW3J1dGFzLCBvbiA9IGMoImxvY2FsIiA9ICJkZXN0aW5vIildICU+JSAKICBzZXRuYW1lcyhjKCJsb2NhbCIpLCBjKCJhZXJvcHVlcnRvIikpICU+JSAKICAuWywgb3JpZ2VuIDo9IE5VTExdCmBgYAoKRmluYWxtZW50ZSwgY29uIGVsIG1hcGEsIGxhcyBydXRhcyB5IGxhIHViaWNhY2nDs24gZGUgbG9zIGFlcm9wdWVydG9zIGxvZ3LDqSBlbCBncsOhZmljbyBxdWUgcXVlcsOtYS4gUGFyYSBncmFmaWNhciBsYXMgcnV0YXMgbGEgY2xhdmUgZXN0w6EgZW4gYWdyZWdhciBsYSBjb2x1bW5hIGBpZF9ydXRhYCBxdWUgbHVlZ28gc2lydmUgcGFyYSBncmFmaWNhciBsaW5lYXMgcG9yIGNhZGEgdW5vIGRlIGVzb3MgZ3J1cG9zIHF1ZSBzZSBmb3JtYW4gY29uIGVsIGFlcm9wdWVydG8gZGUgb3JpZ2VuICB5IGVsIGRlIGRlc3Rpbm8uIAoKYGBge3J9CnJiaW5kKG9yaWdlbiwgZGVzdGlubykgJT4lIAogIC5bLCBhZXJvbGluZWFfbm9tYnJlIDo9IGZvcmNhdHM6OmZjdF9yZWNvZGUoYWVyb2xpbmVhX25vbWJyZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWVyb2xpbmVhcyBBcmdlbnRpbmFzIiA9ICJBRVJPTElORUFTIEFSR0VOVElOQVMgU0EiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGbHlib25kaSIgPSAiRkIgTMONTkVBUyBBw4lSRUFTIC0gRkxZQk9OREkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkpldFNtYXJ0IiA9ICJKRVRTTUFSVCBBSVJMSU5FUyBTLkEuIildICU+JSAKICBnZ3Bsb3QoYWVzKGxvbmdpdHVkLCBsYXRpdHVkKSkgKwogIGdlb21fc2YoZGF0YSA9IG1hcGEsIGluaGVyaXQuYWVzID0gRkFMU0UsIGZpbGwgPSAiZ3JleTk4IikgKwogIGdlb21fcG9pbnQoZGF0YSA9IH5jb3B5KC54KVssIGFlcm9saW5lYV9ub21icmUgOj0gTlVMTF0sIGNvbG9yID0gImdyZXk4MCIsIGFscGhhID0gMC41LCBzaXplID0gMSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IH5jb3B5KC54KVssIGFlcm9saW5lYV9ub21icmUgOj0gTlVMTF0sIGFlcyhncm91cCA9IGlkX3J1dGEpLCAKICAgICAgICAgICAgY29sb3IgPSAiZ3JleTgwIiwgYWxwaGEgPSAwLjUpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGFlcm9saW5lYV9ub21icmUpLCBhbHBoYSA9IDAuNSwgc2l6ZSA9IDEpICsgCiAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IGFlcm9saW5lYV9ub21icmUsIGdyb3VwID0gaWRfcnV0YSksCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiMzNDZFQTMiLCAiI0ZGQkYzNCIsICIjQUExQzJBIiksIGd1aWRlID0gTlVMTCkgKwogIGZhY2V0X3dyYXAofmFlcm9saW5lYV9ub21icmUpICsKICBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCwgY29sb3IgPSBOVUxMLAogICAgICAgdGl0bGUgPSAiUnV0YXMgYcOpcmVhcyBlbiBBcmdlbnRpbmEiLAogICAgICAgc3VidGl0bGUgPSAiRWwgbWVyY2FkbyBlc3TDoSBkb21pbmFkbyBwb3IgQUEgY29uIDE5MCBydXRhcyIsCiAgICAgICBjYXB0aW9uID0gIkZ1ZW50ZTogQWRtaW5pc3RyYWNpw7NuIE5hY2lvbmFsIGRlIEF2aWFjacOzbiBDaXZpbCIpICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEwLAogICAgICAgICAgICAgICAgYmFzZV9mYW1pbHkgPSAiUm9ib3RvIENvbmRlbnNlZCBMaWdodCIpICsKICB0aGVtZShwbG90LnRpdGxlLnBvc2l0aW9uID0gInBsb3QiLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIikpCgojIGdnc2F2ZSgiZGF5Mi5wbmciLCBkZXZpY2UgPSBwbmcsIHR5cGUgPSAiY2Fpcm8iLCBiZyA9ICJ3aGl0ZSIsIHdpZHRoID0gMjUsIGhlaWdodCA9IDE4LCB1bml0cyA9ICJjbSIsIGRwaSA9IDE1MCkKYGBgCg==