library(knitr)
knitr::opts_chunk$set(warning=FALSE, message=FALSE)
library(tidyverse)
library(sf)
library(ggmap)
library(tmap)
library(tmaptools)
library(osmdata)
library(kableExtra)



Geocodificación de domicilios

El dataset que se utilizar para este trabajo corresponde a las comisarías ubicadas en la Ciudad Autónoma de Buenos Aires. Éste fue descargado desde la plataforma del curso Introducción a la Ciencia de Datos que forma parte de la Diplomatura en Ciudades y Políticas Urbanas dictada por la Universidad Torcuatto Di Tella. Además se trabaja con el stamenmap de CABA, utilizandolo como base para facilitar el entendimiento de la posición geográfica de los elementos en el territorio.

df_pstation <- read.csv("data/comisarias.csv", stringsAsFactors = TRUE)
df_pstation <- df_pstation %>% 
  arrange(id)
df_pstation %>% 
  head(10) %>% 
  kbl(align = "c", longtable = TRUE) %>% 
  kable_styling(bootstrap_options = c("striped", "condensed"), font_size = 11)
lon lat id nombre calle altura calle2 direccion telefonos observaciones observaciones_2 barrio comuna codigo_postal codigo_postal_argentino
-58.37324 -34.60191 1 Comisaria Vecinal 1-D Lavalle 451 LAVALLE 451 4322-8033/8221 NA SAN NICOLAS 1 1047 C1047AAI
-58.37415 -34.62028 2 Comisaria Vecinal 1-B (edificio anexo) Peru 1056 PERÚ 1056 4307-0537/4361 -8054 /66 NA SAN TELMO 1 1068 C1068AAL
-58.38890 -34.60194 3 Comisaria Vecinal 1-A Tucuman 1560 TUCUMAN 1560 4371-3333 /4373-6194/4374-0454 NA SAN NICOLAS 1 1050 C1050AAF
-58.37858 -34.61716 4 Comisaria Vecinal 1-B Tacuari 770 TACUARI 770 4331-9643 /4342-3333 NA MONSERRAT 1 1071 C1071AAP
-58.39479 -34.60342 5 Comisaria Comunal 3 Lavalle 1958 LAVALLE 1958 4953-2273/3323 NA BALVANERA 3 1051 C1051ABD
-58.40401 -34.60321 6 Comisaria Vecinal 3-A Lavalle 2625 LAVALLE 2625 4961-3333/7342 / 4964-3421 NA BALVANERA 3 1052 C1052AAG
-58.41556 -34.60443 7 Comisaria Comunal 5 Billinghurst 471 BILLINGHURST 471 4861-5507 /4862-3333 NA ALMAGRO 5 1174 C1174ABG
-58.44809 -34.62678 8 Comisaria Vecinal 7-B Valle 1454 VALLE 1454 4432-3334/3922 Ubicada en comuna 6, dependencia comuna 7 NA CABALLITO 6 1406 C1406GTH
-58.38018 -34.59464 10 Comisaria Comunal 1 Suipacha 1156 SUIPACHA 1156 4393-0076/3333/7058 NA RETIRO 1 1008 C1008AAX
-58.39236 -34.59114 11 Comisaria Comunal 2 Las Heras Gral. 1861 AVENIDA GENERAL LAS HERAS 1861 4801-1698/3333 NA RECOLETA 2 1127 C1127AAA

Mapa base CABA

A partir de las coordenadas del bbox obtenidas desde OpenStreetMap, se descarga el stamenmap de la ciudad de Buenos Aires solicitando un mapa que solo contenga las líneas de tierra en escala de grises. Este mapa ser utilizado posteriormente como base para los gráficos a producir.

bbox_caba <- getbb("Ciudad Autonoma de Buenos Aires, Buenos Aires, Argentina")
basemap_caba <- get_stamenmap(bbox=bbox_caba,
                              maptype="terrain-lines",
                              zoom=12)
ggmap(basemap_caba) +
  theme_void()


Geolocalización mediante coordenadas

En primer lugar se realiza la geolocalización de las comisarías en la Ciudad Autónoma de Buenos Aires a partir de las coordenadas presentes en el dataframe original. Este procedimiento se realiza utilizando la proyección WSG84.

geodf_coords_pstation <- df_pstation %>%
  filter(!is.na(df_pstation$lon) & !is.na(df_pstation$lat)) %>% 
  st_as_sf(coords = c("lon", "lat"), crs = 4326)

Mapa base CABA

En segundo lugar se realiza la geolocalización de las mismas comisarías, pero utilizando en este caso el domicilio brindado en el dataset original. Este procedimiento se realiza realizando una consulta a OpenStreetMap de cada uno de los domicilios y obteniendo la latitud y la longitud de cada punto. Posteriormente, con estas coordenadas obtenidas se geolocaliza cada una de las comisarías.

df_pstation <- df_pstation %>% 
  mutate(adress=paste0(direccion, ', CABA, Argentina'))
adresses_pstation <- list(df_pstation$adress)
geocode_df <- function(x){
  geocode_adresses <- geocode_OSM(x, as.data.frame = TRUE)
  geocode_adresses$adress <- geocode_adresses$query
  df <- select(geocode_adresses, adress, lat, lon)
}
adresses_pstation <- pmap(adresses_pstation, geocode_df) %>% 
  reduce(rbind)
adresses_pstation %>% 
  head(5) %>% 
  kbl(align = "c", longtable = TRUE) %>% 
  kable_styling(bootstrap_options = c("striped", "condensed"), font_size = 11)
adress lat lon
LAVALLE 451, CABA, Argentina -34.60199 -58.37325
PERÚ 1056, CABA, Argentina -34.60858 -58.37450
TUCUMAN 1560, CABA, Argentina -34.60185 -58.38895
TACUARI 770, CABA, Argentina -34.61724 -58.37862
LAVALLE 1958, CABA, Argentina -34.60341 -58.39482
geodf_adresses_pstation <- df_pstation %>% 
  select(-c("lon", "lat")) %>% 
  left_join(adresses_pstation)
geodf_adresses_pstation <- st_as_sf(geodf_adresses_pstation, coords=c("lon", "lat"), crs = 4326)
geodf_adresses_pstation %>% 
  head(5) %>% 
  kbl(align = "c", longtable = TRUE) %>% 
  kable_styling(bootstrap_options = c("striped", "condensed"), font_size = 11)
id nombre calle altura calle2 direccion telefonos observaciones observaciones_2 barrio comuna codigo_postal codigo_postal_argentino adress geometry
1 Comisaria Vecinal 1-D Lavalle 451 LAVALLE 451 4322-8033/8221 NA SAN NICOLAS 1 1047 C1047AAI LAVALLE 451, CABA, Argentina POINT (-58.37325 -34.60199)
2 Comisaria Vecinal 1-B (edificio anexo) Peru 1056 PERÚ 1056 4307-0537/4361 -8054 /66 NA SAN TELMO 1 1068 C1068AAL PERÚ 1056, CABA, Argentina POINT (-58.3745 -34.60858)
3 Comisaria Vecinal 1-A Tucuman 1560 TUCUMAN 1560 4371-3333 /4373-6194/4374-0454 NA SAN NICOLAS 1 1050 C1050AAF TUCUMAN 1560, CABA, Argentina POINT (-58.38895 -34.60185)
4 Comisaria Vecinal 1-B Tacuari 770 TACUARI 770 4331-9643 /4342-3333 NA MONSERRAT 1 1071 C1071AAP TACUARI 770, CABA, Argentina POINT (-58.37862 -34.61724)
5 Comisaria Comunal 3 Lavalle 1958 LAVALLE 1958 4953-2273/3323 NA BALVANERA 3 1051 C1051ABD LAVALLE 1958, CABA, Argentina POINT (-58.39482 -34.60341)
geodf_adresses_pstation %>% 
  summary()
##        id                         nombre                         calle   
##  Min.   : 1.00   Comisaria Comunal 1 : 1   Lavalle                  : 3  
##  1st Qu.:15.00   Comisaria Comunal 10: 1   Ana Diaz                 : 1  
##  Median :29.00   Comisaria Comunal 11: 1   Artilleros               : 1  
##  Mean   :29.45   Comisaria Comunal 12: 1   Av. Cnel Esteban Bonorino: 1  
##  3rd Qu.:44.00   Comisaria Comunal 13: 1   Av. Ing. Huergo          : 1  
##  Max.   :57.00   Comisaria Comunal 14: 1   Av. San Juan             : 1  
##                  (Other)             :43   (Other)                  :41  
##      altura          calle2                                  direccion 
##  Min.   :   0           :48   ALFREDO R. BUFANO 1800              : 1  
##  1st Qu.: 645   Cafayate: 1   ARTILLEROS 2081                     : 1  
##  Median :1560                 AVELLANEDA AV. 1548                 : 1  
##  Mean   :1944                 AVENIDA CABILDO 232                 : 1  
##  3rd Qu.:2844                 AVENIDA CORONEL ESTEBAN BONORINO 258: 1  
##  Max.   :5437                 AVENIDA DIAZ VELEZ 5152             : 1  
##                               (Other)                             :43  
##                       telefonos 
##                            : 2  
##  4300-6338 / 4307-4644/5153: 1  
##  4301-3333                 : 1  
##  4304-3203/4300 /4305-3333 : 1  
##  4306-3333/4067            : 1  
##  4307-0537/4361 -8054 /66  : 1  
##  (Other)                   :42  
##                                                                  observaciones
##                                                                         :44   
##  Esta comisaria cuenta con una dependencia del Ministerio Publico Fiscal: 3   
##  Ubicada en comuna 12, dependencia comuna 11                            : 1   
##  Ubicada en comuna 6, dependencia comuna 7                              : 1   
##                                                                               
##                                                                               
##                                                                               
##  observaciones_2           barrio       comuna       codigo_postal 
##  Mode:logical    BALVANERA    : 3   Min.   : 1.000   Min.   :1008  
##  NA's:49         CABALLITO    : 3   1st Qu.: 3.000   1st Qu.:1164  
##                  PALERMO      : 3   Median : 7.000   Median :1408  
##                  VILLA URQUIZA: 3   Mean   : 7.163   Mean   :1311  
##                  BARRACAS     : 2   3rd Qu.:12.000   3rd Qu.:1427  
##                  BELGRANO     : 2   Max.   :15.000   Max.   :1440  
##                  (Other)      :33                    NA's   :3     
##  codigo_postal_argentino    adress                   geometry 
##          : 3             Length:49          POINT        :49  
##  C1008AAX: 1             Class :character   epsg:4326    : 0  
##  C1047AAI: 1             Mode  :character   +proj=long...: 0  
##  C1050AAF: 1                                                  
##  C1051ABD: 1                                                  
##  C1052AAG: 1                                                  
##  (Other) :41

Gráfica comparativa

Aplicando el color naranja para las coordenadas existentes en el dataframe original, y el violeta para las coordenadas consultadas en OpenStreetMap, se grafica la ubicación de cada una de las comisarías sobre el mapa base de Buenos Aires.

ggmap(basemap_caba) +
  geom_sf(data=geodf_coords_pstation, color="#b35806", shape=20, size=2, alpha=1, inherit.aes=FALSE) +
  geom_sf(data=geodf_adresses_pstation, color="#542788", shape=20, size=1.5, alpha=0.9, inherit.aes=FALSE) +
  theme_light() +
  labs(title = "Error segun fuente de las coordenadas de comisarías en CABA",
       x = NULL,
       y = NULL,
       caption = ("Fuente: OSM / BsAs Data")) +
  theme(plot.margin = margin(15, 5, 15, 5),
        aspect.ratio = 1,
        panel.grid.major = element_line(color = "gray80",
                                        linetype = "dashed"),
        panel.background = element_rect(fill = "white",
                                        colour = "gray100",
                                        size = 2,
                                        linetype = "solid"),
        plot.title = element_text(size = 10,
                                  face = "bold",
                                  hjust = .5,
                                  vjust = 2.5,
                                  colour = "gray20"),
        plot.caption = element_text(size = 5,
                                    colour = "gray20"),
        axis.text.x = element_text(size = 5,
                                    colour = "gray20"),
        axis.text.y = element_text(size = 5,
                                    colour = "gray20"),
        legend.position = "right",
        legend.title = element_text(size = 10,
                                    colour = "gray20"),
        legend.text  = element_text(size = 7.5,
                                    colour = "gray20")
        )

El plano resultante da cuenta de una gran precisión en la amplia mayoría de las comisarías. Sin embargos se detectan diferencias en algunas de ellas, aparentemente aleatorias. Para distingir cuales de ellas presentan un error de posicionamiento significativo ser interesante calcular las distancias entre las coordenadas brindadas por el dataset y las obtenidas desde OpenStreetMap.


Calculo de errores

A través de la conversión al sistema de proyección POSGAR 94, se calcula la distancia, en metros, del error entre las coordenadas brindadas por el dataset original y las obtenidas a través de la consulta a OpenStreetMap. Posteriormente se conserva el ‘id’ de las comisarías en cuyos casos el error es mayor a 100 metros.

geodf_coords_pstation_posgar <- geodf_coords_pstation %>% 
  st_transform(crs = 32610)

geodf_adresses_pstation_posgar <- geodf_adresses_pstation %>% 
  st_transform(crs = 32610)
df_distance_error <- df_pstation %>% 
  select("id") %>% 
  mutate(
    error = (
      st_distance(geodf_coords_pstation_posgar$geometry, geodf_adresses_pstation_posgar$geometry, by_element=TRUE) %>% 
        as.numeric() %>%
        round(.,2)
      )
    )
df_distance_error %>% 
  arrange(desc(error)) %>% 
  filter(error>100)
##   id   error
## 1 18 2871.40
## 2  2 1940.13
## 3 21  781.00
## 4 37  261.31
## 5 44  172.92
top_error_id <- df_distance_error %>% 
  arrange(desc(error)) %>% 
  filter(error>100)

Gráfica comparativa

Aplicando el color naranja para las coordenadas existentes en el dataframe original, y el violeta para las coordenadas consultadas en OpenStreetMap, se grafica la ubicación de cada una de las comisarías cuyo error de posicionamiento entre ambas coordenadas es mayor a 100 metros.

ggmap(basemap_caba) +
  geom_sf(data=filter(geodf_coords_pstation, id %in% top_error_id$id), color="#b35806", shape=20, size=2, inherit.aes=FALSE) +
  geom_sf(data=filter(geodf_adresses_pstation, id %in% top_error_id$id), color="#542788", shape=20, size=2, inherit.aes=FALSE) +
  theme_light() +
  labs(title = "Error segun fuente de las coordenadas de comisarías en CABA",
       x = NULL,
       y = NULL,
       caption = ("Fuente: OSM / BsAs Data")) +
  theme(plot.margin = margin(15, 5, 15, 5),
        aspect.ratio = 1,
        panel.grid.major = element_line(color = "gray80",
                                        linetype = "dashed"),
        panel.background = element_rect(fill = "white",
                                        colour = "gray100",
                                        size = 2,
                                        linetype = "solid"),
        plot.title = element_text(size = 10,
                                  face = "bold",
                                  hjust = .5,
                                  vjust = 2.5,
                                  colour = "gray20"),
        plot.caption = element_text(size = 5,
                                    colour = "gray20"),
        axis.text.x = element_text(size = 5,
                                    colour = "gray20"),
        axis.text.y = element_text(size = 5,
                                    colour = "gray20"),
        legend.position = "right",
        legend.title = element_text(size = 10,
                                    colour = "gray20"),
        legend.text  = element_text(size = 7.5,
                                    colour = "gray20")
        )

Puede observarse la aparente aleatoreidad en la ubicación de las comisarías con amplio margen de error. Tras una rápida búsqueda en google maps de la comisaría con el mayor márgen de error (id = 18) encontramos que la consulta por el domicilio ‘Cuba 3147’ devolvió la ubicación del club CUBA. Esta situación nos advierte sobre la necesidad de trabajar con este recurso con mucho cuidado, ya que a pesar del gran potencial que tiene, nos puede conducir, en determinados casos, a errores significativos.