library(tidyverse)
## ── Attaching packages ────────────────────────────────────────────────── tidyverse 1.3.0 ──
## ✓ ggplot2 3.3.0 ✓ purrr 0.3.3
## ✓ tibble 3.0.1 ✓ dplyr 0.8.5
## ✓ tidyr 1.0.2 ✓ stringr 1.4.0
## ✓ readr 1.3.1 ✓ forcats 0.5.0
## ── Conflicts ───────────────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
library(sf)
## Linking to GEOS 3.7.2, GDAL 2.4.2, PROJ 5.2.0
I. Deberán elegir una ciudad en cualquier parte del mundo que les interese y que disponga de un portal de datos abiertos que ofrece un shapefile con sus barrios. Elegimos la ciudad de Barcelona y a continuación cargaremos el dataframe que brinda la página del Ayuntamiento con los límites de sus barrios y distritos (comunas).
Barcelona_distritos <- st_read("bcn_UNITATS_ADM_POLIGONS.json")
## Reading layer `bcn_UNITATS_ADM_POLIGONS' from data source `/Users/lousil/Google Drive/Formación Académica/ECONOMIA URBANA/14. CIENCIA DE DATOS PARA CIUDADES/Ciencia de Datos para Ciudades I/Clase 1/Ciencia de Datos para ciudades 2/bcn_UNITATS_ADM_POLIGONS.json' using driver `GeoJSON'
## Simple feature collection with 1501 features and 35 fields
## geometry type: MULTIPOLYGON
## dimension: XY
## bbox: xmin: 420812.5 ymin: 4574282 xmax: 435480.4 ymax: 4591066
## CRS: 25831
Vemos que el sistema de coordenadas de referencia (CRS) es 25831, por lo tanto no es Merkator. Vamos a cambiarlo:
Barcelona_distritos <- st_transform(Barcelona_distritos, crs = 4326)
names(Barcelona_distritos)
## [1] "FID" "ID_ANNEX" "ANNEXDESCR" "ID_TEMA" "TEMA_DESCR"
## [6] "ID_CONJUNT" "CONJ_DESCR" "ID_SUBCONJ" "SCONJ_DESC" "ID_ELEMENT"
## [11] "ELEM_DESCR" "NIVELL" "NDESCR_CA" "NDESCR_ES" "NDESCR_EN"
## [16] "TERME" "DISTRICTE" "BARRI" "AEB" "SEC_CENS"
## [21] "GRANBARRI" "ZUA" "AREA_I" "LITERAL" "PERIMETRE"
## [26] "AREA" "CODI_UA" "TIPUS_UA" "NOM" "WEB1"
## [31] "WEB2" "WEB3" "FHEX_COLOR" "Shape_Leng" "Shape_Area"
## [36] "geometry"
Como el dataset posee 36 variables, de las cual necesitamos solo unas pocas, seleccionaremos y filtraremos solo lo que necesitamos para disminuir el gran tamaño del archivo:
Barcelona_distritos <- Barcelona_distritos %>%
filter(!(DISTRICTE =="-")) %>%
group_by(DISTRICTE) %>%
summarise()
Equipamientos <- read.csv("bcn_Biblioteques_i_museus.csv")
Por alguna razón que desconocemos, aparecen varias observaciones del mismo equipamiento. Por tal motivo, agruparemos segun equipamiento para que nos quede una observación para cada uno y luego las cuente correctamente.
Equipamientos <- Equipamientos %>%
group_by(EQUIPAMENT, LONGITUD, LATITUD) %>%
summarise()
Visualicemos ambos datasets superpuestos:
ggplot()+
geom_sf(data = Barcelona_distritos, aes(fill=DISTRICTE), color = NA) +
geom_point(data = Equipamientos, aes(x=LONGITUD, y=LATITUD), alpha=.8) +
labs(title = "Equipamiento por distrito ",
subtitle = "(museos, bibliotecas, universidades, etc)",
fill = "Distritos",
caption= "Fuente: Ajuntament de Barcelona | 2020",
y="",
x="")
Convertimos el dataset de Bibliotecas y Museos a espacial:
Equipamientos <- Equipamientos %>%
st_as_sf(coords = c("LONGITUD", "LATITUD"), crs = 4326)
…Y unimos al dataset que contiene los límites de barrios y distritos (comunas) de Barcelona:
Equipamientos <- st_join(Barcelona_distritos, Equipamientos)
## although coordinates are longitude/latitude, st_intersects assumes that they are planar
Equipamientos_distritos <- Equipamientos %>%
group_by(DISTRICTE) %>%
summarise(Frecuencia = n())
ggplot(Equipamientos_distritos) +
geom_bar(aes( x = DISTRICTE, weight = Frecuencia), fill="#69b3a2") +
labs(title = "Cantidad de Equipamiento por distrito",
subtitle = "(museos, bibliotecas, universidades, etc)",
caption= "Fuente: Ajuntament de Barcelona | 2020",
y="Cantidad",
x="Distritos")
Ahora ponderaremos según cantidad de Museos y Bibliotecas por distrito con scale_viridis:
ggplot(Equipamientos_distritos) +
geom_bar(aes( x = DISTRICTE, weight = Frecuencia, fill=Frecuencia)) +
scale_fill_viridis_c() +
labs(title = "Cantidad de Equipamiento por distrito",
subtitle = "(museos, bibliotecas, universidades, etc)",
fill = "Escala",
caption= "Fuente: Ajuntament de Barcelona | 2020",
y="Cantidad",
x="Distritos")
ggplot() +
geom_sf(data = Equipamientos_distritos, aes(fill=Frecuencia), color = NA) +
geom_sf_text(data = Equipamientos_distritos, aes(label = DISTRICTE), size = 2, colour = "white") +
scale_fill_viridis_c() +
labs(title = "Cantidad de Equipamiento por distrito",
subtitle = "(museos, bibliotecas, universidades, etc)",
fill = "Escala",
caption= "Fuente: Ajuntament de Barcelona | 2020",
y="",
x="")
## Warning in st_point_on_surface.sfc(sf::st_zm(x)): st_point_on_surface may not
## give correct results for longitude/latitude data
I. Descargar de OpenStreetMap la grilla de calles para la Ciudad elegida en el ejercicio 1 y mapearla por uno de sus atributos (velocidad mínima, velocidad máxima, cantidad de carriles, etc).
library(osmdata)
## Data (c) OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright
library(leaflet)
Barcelona <- getbb("Barcelona, España")
Barcelona
## min max
## x 2.052498 2.228356
## y 41.317035 41.467914
ciudad <- "Barcelona"
posicion <- 1
url <- URLencode(paste0("https://nominatim.openstreetmap.org/search.php?q=",
ciudad, "&polygon_geojson=1&format=geojson"))
destfile = paste0(tempdir(), "/limits.json")
download.file(url, destfile)
Barcelona_frontera <- st_read(destfile)[posicion,]
## Reading layer `limits' from data source `/private/var/folders/lg/vhfpqlf52vj3nv4pgd4px5pm0000gn/T/Rtmp8OMREb/limits.json' using driver `GeoJSON'
## Simple feature collection with 10 features and 9 fields
## geometry type: GEOMETRY
## dimension: XY
## bbox: xmin: -80.6871 ymin: -6.069389 xmax: 124.1419 ymax: 50.3547
## CRS: 4326
leaflet(Barcelona_frontera) %>%
addTiles() %>%
addPolygons()
A continuación construiremos la consulta, especificando los datos que queremos descargar:
Barcelona_calles <- opq(Barcelona) %>%
add_osm_feature(key="highway")
Con osmdata() recolectamos la información de la consulta en forma de dataset espacial:
Barcelona_calles <- Barcelona_calles %>%
osmdata_sf()
Barcelona_calles
## Object of class 'osmdata' with:
## $bbox : 41.3170353,2.0524977,41.4679135,2.2283555
## $overpass_call : The call submitted to the overpass API
## $meta : metadata including timestamp and version numbers
## $osm_points : 'sf' Simple Features Collection with 245460 points
## $osm_lines : 'sf' Simple Features Collection with 46106 linestrings
## $osm_polygons : 'sf' Simple Features Collection with 1632 polygons
## $osm_multilines : NULL
## $osm_multipolygons : 'sf' Simple Features Collection with 87 multipolygons
Extraemos las calles en forma de línea:
Barcelona_calles <- Barcelona_calles$osm_lines
Y graficamos:
ggplot() +
geom_sf(data = Barcelona_calles, color = "gray20")
A continuación haremos una interesección entre los límites de la ciudad y las calles obtenidas a través de OSM:
Barcelona_calles <- st_intersection(Barcelona_calles, Barcelona_frontera)
## although coordinates are longitude/latitude, st_intersection assumes that they are planar
## Warning: attribute variables are assumed to be spatially constant throughout all
## geometries
Y graficamos:
ggplot()+
geom_sf(data=Barcelona_calles, color = "gray20")
Para mapearla por el atributo de velocidad máxima, haremos:
Barcelona_callesmax <- Barcelona_calles %>%
mutate(maxspeed = as.numeric(maxspeed),
lanes = ifelse(is.na(lanes), 1, as.numeric(lanes)))
Y graficamos:
ggplot(Barcelona_callesmax) +
geom_sf(aes(color = maxspeed), alpha = 0.5) +
scale_color_viridis_c() +
theme_void() +
labs(title = "Barcelona",
subtitle = "Vías de circulación",
caption = "fuente: OpenStreetMap",
color = "velocidad máxima")
Elegimos descargar la capa de datos de las bibliotecas:
Barcelona_bibliotecas <- opq(Barcelona) %>%
add_osm_feature(key = "amenity", value = "library") %>%
osmdata_sf()
Y la de museos:
Barcelona_museos <- opq(Barcelona) %>%
add_osm_feature(key = "tourism", value = "museum") %>%
osmdata_sf()
Y la de universidades:
Barcelona_universidades <- opq(Barcelona) %>%
add_osm_feature(key = "amenity", value = "university") %>%
osmdata_sf()
Barcelona_bibliotecas <- Barcelona_bibliotecas$osm_points
Barcelona_museos <- Barcelona_museos$osm_points
Barcelona_universidades <- Barcelona_universidades$osm_points
Barcelona_bibliotecas <- st_intersection(Barcelona_bibliotecas, Barcelona_frontera) %>%
select(name, geometry) %>%
filter(!is.na(name))
## although coordinates are longitude/latitude, st_intersection assumes that they are planar
## Warning: attribute variables are assumed to be spatially constant throughout all
## geometries
Barcelona_museos <- st_intersection(Barcelona_museos, Barcelona_frontera) %>%
select(name, geometry) %>%
filter(!is.na(name))
## although coordinates are longitude/latitude, st_intersection assumes that they are planar
## Warning: attribute variables are assumed to be spatially constant throughout all
## geometries
Barcelona_universidades <- st_intersection(Barcelona_universidades, Barcelona_frontera) %>%
select(name, geometry) %>%
filter(!is.na(name))
## although coordinates are longitude/latitude, st_intersection assumes that they are planar
## Warning: attribute variables are assumed to be spatially constant throughout all
## geometries
ggplot()+
geom_sf(data = Barcelona_calles, color = "gray20") +
geom_sf(data = Barcelona_bibliotecas, color = "purple") +
geom_sf(data = Barcelona_museos, color = "salmon") +
geom_sf(data = Barcelona_universidades, color = "royalblue") +
labs(title = "Barcelona",
subtitle = "Bibliotecas, Museos y Universidades",
caption = "fuente: OpenStreetMap")
Como podemos observar, los museos parecen estar agrupados en lugares específicos y turísticos, como ser en la antigua ciudad amurallada (Ciutat Vella) y la Rambla, así como en la montaña Montjuic. Respecto a las universidades, podemos ver un gran concentración en un extremo de la ciudad, siendo la menor distribución del lado opuesto. Sin embargo, las bibliotecas tienen una distribución más pareja en el territorio. Podemos suponer que exista alguna política pública que asegure una distribución pareja de bibliotecas por barrio.
Cargamos las siguientes librerías:
library(devtools)
## Loading required package: usethis
library(ggsflabel)
##
## Attaching package: 'ggsflabel'
## The following objects are masked from 'package:ggplot2':
##
## geom_sf_label, geom_sf_text, StatSfCoordinates
Y ahora agregamos las etiquetas, sólo para el caso de las bibliotecas:
ggplot() +
geom_sf(data = Barcelona_calles, color = "gray20") +
geom_sf_label_repel(data = Barcelona_bibliotecas, aes(label = name), size = 2, color = "purple") +
theme_void() +
labs(title = "Barcelona",
subtitle = "Bibliotecas con etiquetas",
caption = "fuente: OpenStreetMap")
## Warning in st_point_on_surface.sfc(data$geometry): st_point_on_surface may not
## give correct results for longitude/latitude data
Primero que nada vamos a unir los shapes de bibliotecas, museos y universidades en un solo:
Barcelona_bibliotecas_museos_universidades <- rbind(Barcelona_bibliotecas, Barcelona_museos, Barcelona_universidades)
Haremos un join espacial entre el shape de bibliotecas, universidades y museos unido anteriormente y el shape que contiene los distritos:
osm_bmu_distritos <- st_join(Barcelona_bibliotecas_museos_universidades, Barcelona_distritos)
## although coordinates are longitude/latitude, st_intersects assumes that they are planar
## although coordinates are longitude/latitude, st_intersects assumes that they are planar
Hacemos un conteo agrupando por distrito y sacándole la geometría:
osm_bmu_distritos <- osm_bmu_distritos %>%
group_by(DISTRICTE) %>%
summarise(Frecuencia = n()) %>%
st_set_geometry(NULL)
Con left_join() unimos el conteo anterior con el shape que tiene los límites de los distritos:
osm_bmu_distritos <- left_join(Barcelona_distritos, osm_bmu_distritos, by="DISTRICTE")
Y graficamos:
ggplot() +
geom_sf(data = osm_bmu_distritos, aes(fill = Frecuencia), color=NA) +
geom_sf_text(data = osm_bmu_distritos, aes(label = Frecuencia), size = 2, colour = "white") +
scale_fill_viridis_c() +
labs(title = "Barcelona",
subtitle = "Bibliotecas, Museos y Universidades por Distritos",
caption = "fuente: OpenStreetMap",
y="",
x="")
## Warning in st_point_on_surface.sfc(data$geometry): st_point_on_surface may not
## give correct results for longitude/latitude data
Vemos que la frecuencia máxima es de 31 para el Distrito Nº1, coloreado en amarillo.
Comparemos ahora con el gráfico hecho anteriormente:
ggplot() +
geom_sf(data = Equipamientos_distritos, aes(fill=Frecuencia), color = NA) +
geom_sf_text(data = Equipamientos_distritos, aes(label = Frecuencia), size = 2, colour = "white") +
scale_fill_viridis_c() +
labs(title = "Barcelona",
subtitle = "Bibliotecas, Museos y Universidades por Distritos",
fill = "Escala",
caption= "Fuente: Ajuntament de Barcelona | 2020",
y="",
x="")
## Warning in st_point_on_surface.sfc(data$geometry): st_point_on_surface may not
## give correct results for longitude/latitude data
En este mapa, hecho en el módulo anterior con data abierta que brinda el Ayuntamiento de Barcelona, la Frecuencia máxima llega a los 70. Además, la cantidad de observaciones en cada Distrito es mayor a la observada con los datos de OSM. Por tal motivo entendemos que los datos brindados por el ayuntamiento incluyen otros equipamientos, además de bibliotecas museos y universidades, y esto hace que difiera la frecuencia en cada distrito.
Comprobémemoslo ahora numéricamente:
summary(Equipamientos_distritos)
## DISTRICTE Frecuencia geometry
## 01 :1 Min. : 7.00 MULTIPOLYGON :2
## 02 :1 1st Qu.:10.75 POLYGON :8
## 03 :1 Median :20.50 epsg:4326 :0
## 04 :1 Mean :26.20 +proj=long...:0
## 05 :1 3rd Qu.:26.00
## 06 :1 Max. :70.00
## (Other):4
En este dataset hecho en el módulo Nº1, la frecuencia máxima alcanza las 70 observaciones en el Distrito 1 y además el promedio es 26.20.
summary(osm_bmu_distritos)
## DISTRICTE geometry Frecuencia
## 01 :1 MULTIPOLYGON :2 Min. : 2.00
## 02 :1 POLYGON :8 1st Qu.: 3.50
## 03 :1 epsg:4326 :0 Median : 7.00
## 04 :1 +proj=long...:0 Mean :10.70
## 05 :1 3rd Qu.:17.25
## 06 :1 Max. :32.00
## (Other):4
En cambio, en este dataset hecho con información de OSM vemos que la frecuencia máxima es 31 y el promedio es 10,60.
I. Utilizar los tweets que descargaron en el ejercicio anterior o elegir algún dataset open data de la Ciudad que tenga tanto coordenadas como fecha.
Cargamos un dataset bajado del Open Data de la ciudad de Barcelona que contiene los reclamos de los ciudadanos finalizados en 2019:
bcn_reclamos <- read.csv("Clase_9_2019_peticions_ciutadanes.csv")
names(bcn_reclamos)
## [1] "FITXA_ID" "TIPUS" "AREA"
## [4] "ELEMENT" "DETALL" "DIA_DATA_ALTA"
## [7] "MES_DATA_ALTA" "ANY_DATA_ALTA" "DIA_DATA_TANCAMENT"
## [10] "MES_DATA_TANCAMENT" "ANY_DATA_TANCAMENT" "CODI_DISTRICTE"
## [13] "DISTRICTE" "CODI_BARRI" "BARRI"
## [16] "SECCIO_CENSAL" "TIPUS_VIA" "CARRER"
## [19] "NUMERO" "COORDENADA_X" "COORDENADA_Y"
## [22] "LONGITUD" "LATITUD" "SUPORT"
## [25] "CANALS_RESPOSTA"
Vemos que el dataset contiene 2 fechas, la del origen del reclamo y la fecha de cierre del mismo. A su vez, estas fechas estan divididas por columnas, es decir, hay una columna para el día, una para el mes y otra para el año.
Componemos ahora la variable fecha (de alta y cierre) y las transformamos al formato fecha(día-mes-año):
bcn_reclamos <- bcn_reclamos %>%
mutate(fecha_alta = paste(DIA_DATA_ALTA, MES_DATA_ALTA, ANY_DATA_ALTA)) %>%
mutate(fecha_alta = dmy(fecha_alta)) %>%
mutate(fecha_cierre = paste(DIA_DATA_TANCAMENT, MES_DATA_TANCAMENT, ANY_DATA_TANCAMENT)) %>%
mutate(fecha_cierre = dmy(fecha_cierre))
Hagamos un gráfico de barras que nos permita analizar el mes de origen de los reclamos en 2019:
ggplot(bcn_reclamos %>% filter(year(fecha_alta) == 2019)) +
geom_bar(aes(x = month(fecha_alta, label = TRUE)), fill = "salmon") +
labs(title = "Reclamos dados de alta en 2019",
subtitle = "Barcelona",
x = "Mes",
y = "Cantidad",
caption = "Fuente: Ajuntament de Barcelona")
Podemos observar una tendencia creciente a efectuar reclamos a medida que se acerca el verano europeo, y una tendencia decresciente hacia el invierno. Hay una clara excepción que es el mes de Agosto, podemos deducir que algunas oficinas se encuentren cerradas durante este mes, o que la población se encuentre de vacaciones.
Analicemos ahora el mes de cierre de estos reclamos:
ggplot(bcn_reclamos) +
geom_bar(aes(x = month(fecha_cierre, label = TRUE)), fill = "#69b3a2") +
labs(title = "Reclamos finalizados en 2019",
subtitle = "Barcelona",
x = "Mes",
y = "Cantidad",
caption = "Fuente: Ajuntament de Barcelona")
Acá la distribución es más pareja, destacándose algunos meses como mayo, julio y octubre.
Quedémosnos con los reclamos dados de alta en 2019 y mostremos su composición. Hagamos primero un top 5 de los reclamos por frecuencia:
bcn_reclamos %>%
count(TIPUS) %>%
top_n(5) %>%
arrange(desc(n))
## Selecting by n
## # A tibble: 5 x 2
## TIPUS n
## <fct> <int>
## 1 INCIDENCIA 131348
## 2 CONSULTA 53299
## 3 QUEIXA 37984
## 4 SUGGERIMENT 13339
## 5 PETICIO DE SERVEI 10562
Ahora guardemoslo como un vector con pull():
reclamos_frecuentes <- bcn_reclamos %>%
count(TIPUS) %>%
top_n(5) %>%
pull(TIPUS)
## Selecting by n
Y grafiquemos con un gráfico de barras apilado mostrando en la composición de las barras el tipo de reclamo:
bcn_reclamos %>%
filter(year(fecha_alta) == 2019,
TIPUS %in% reclamos_frecuentes) %>%
ggplot() +
geom_bar(aes(x = month(fecha_alta, label = TRUE), fill =TIPUS)) +
labs(title = "Reclamos finalizados en 2019",
subtitle = "Barcelona, Gráfico de barras apilado",
x = "Mes",
y = "Cantidad",
fill = "Tipo",
caption = "Fuente: Ajuntament de Barcelona")
Y sin apilar:
bcn_reclamos %>%
filter(year(fecha_alta) == 2019,
TIPUS %in% reclamos_frecuentes) %>%
ggplot() +
geom_bar(aes(x = month(fecha_alta, label = TRUE), fill =TIPUS), position = "dodge") +
labs(title = "Reclamos finalizados en 2019",
subtitle = "Barcelona, Gráfico de barras sin apilar",
x = "Mes",
y = "Cantidad",
fill = "Tipo",
caption = "Fuente: Ajuntament de Barcelona")
Vemos que el tipo de reclamo con mayor frecuencia es sin dudas la Incidencia, seguida de la queja y la consulta.
Hagamos ahora un gráfico de líneas:
conteo_mensual <- bcn_reclamos %>%
filter(year(fecha_alta) == 2019,
TIPUS %in% reclamos_frecuentes) %>%
count(TIPUS, mes = month(fecha_alta, label = TRUE))
ggplot(conteo_mensual) +
geom_line(aes(x = mes, y = n, group = TIPUS, color = TIPUS))+
labs(title = "Reclamos finalizados en 2019",
subtitle = "Barcelona, Gráfico de líneas",
x = "Mes",
y = "Cantidad",
color = "Tipo",
caption = "Fuente: Ajuntament de Barcelona")
Ésta última opción es sin dudas la más clara, tanto para mostrar la diferencia relativa en el volumen de incidentes, como para indicar si existen fluctuaciones.
Grafiquemos según el día de la semana:
conteo_semanal <- bcn_reclamos %>%
filter(year(fecha_alta) == 2019,
TIPUS %in% reclamos_frecuentes) %>%
count(TIPUS, diasemana = wday(fecha_alta, label = TRUE))
ggplot(conteo_semanal) +
geom_line(aes(x = diasemana, y = n, group = TIPUS, color = TIPUS)) +
labs(title = "Reclamos finalizados en 2019",
subtitle = "Barcelona, Gráfico de líneas",
x = "Día de la semana",
y = "Cantidad",
color = "Tipo",
caption = "Fuente: Ajuntament de Barcelona")
Vemos que el lunes es el día con mayor cantidad de reclamos y va disminuyendo paulatinamente a lo largo de la semana. Durante el fin de sema las observaciones son mucho menores.
Veamoslo en porcentaje:
conteo_porcentual <- conteo_semanal %>%
group_by(TIPUS) %>%
mutate(pct = n / sum(n) * 100)
ggplot(conteo_porcentual) +
geom_line(aes(x = diasemana, y = pct, group = TIPUS, color = TIPUS)) +
labs(title = "Reclamos finalizados en 2019",
subtitle = "Barcelona, Gráfico de líneas Porcentual %",
x = "Día de la semana",
y = "Cantidad",
color = "Tipo",
caption = "Fuente: Ajuntament de Barcelona")
Vemos que todos los tipos de reclamo tienen el mismo comportamiento, en cuanto a la distribución de la semana. Forcemos al gráfico a comenzar desde 0 el eje y:
ggplot(conteo_porcentual) +
geom_line(aes(x = diasemana, y = pct, group = TIPUS, color = TIPUS))+
expand_limits(y = 0) +
labs(title = "Reclamos finalizados en 2019",
subtitle = "Barcelona, Gráfico de líneas Porcentual %",
x = "Día de la semana",
y = "Cantidad",
color = "Tipo",
caption = "Fuente: Ajuntament de Barcelona")
Vemos que en este caso la respuesta es muy parecida.
Antes que nada filtremos las observaciones que no tienen coordenadas.
bcn_reclamos <- bcn_reclamos %>%
filter(!is.na(LONGITUD), !is.na(LATITUD))
Ahora obtengamos la “bounding box” de nuestros datos, y luego se los pasamos a get_stamenmap() para hacer el mapa:.
bbox <- make_bbox(bcn_reclamos$LONGITUD, bcn_reclamos$LATITUD)
MAPA <- get_stamenmap(bbox = bbox, maptype = "toner-lite", zoom = 12)
## Source : http://tile.stamen.com/toner-lite/12/2071/1528.png
## Source : http://tile.stamen.com/toner-lite/12/2072/1528.png
## Source : http://tile.stamen.com/toner-lite/12/2073/1528.png
## Source : http://tile.stamen.com/toner-lite/12/2071/1529.png
## Source : http://tile.stamen.com/toner-lite/12/2072/1529.png
## Source : http://tile.stamen.com/toner-lite/12/2073/1529.png
## Source : http://tile.stamen.com/toner-lite/12/2071/1530.png
## Source : http://tile.stamen.com/toner-lite/12/2072/1530.png
## Source : http://tile.stamen.com/toner-lite/12/2073/1530.png
ggmap(MAPA)
Hagamos ahora el mapa de densidad:
ggmap(MAPA) +
geom_bin2d(data = bcn_reclamos,
aes(x = LONGITUD, y = LATITUD), alpha=.9) +
labs(title = "Densidad de reclamos",
subtitle = "Barcelona",
x = "Longitud",
y = "Latitud",
fill = "Cantidad",
caption = "Fuente: Ajuntament de Barcelona")
Mejorémoslo aumentando la cantidad de celdas para aumentar la resolución y utilicemos la escala viridis para detecter diferencias por tonalidad con mayor facilidad:
ggmap(MAPA) +
geom_bin2d(data = bcn_reclamos,
aes(x = LONGITUD, y = LATITUD), bins=100, alpha=.9) +
scale_fill_viridis_c() +
labs(title = "Densidad de reclamos",
subtitle = "Barcelona",
x = "Longitud",
y = "Latitud",
fill = "Cantidad",
caption = "Fuente: Ajuntament de Barcelona")
Vemos según el grafico que en los limites de la ciudad es donde menor cantidad de reclamos hay, destándose varias zonas que alcanzan un color verde amarillento.
Utilicemos ahora Kernel Density Estimation, muy utilizada en aplicaciones GIS para estimar la intensidad de una determinada variable en cualquier punto del área analizada, incluso en aquellos donde no hay observaciones:
ggmap(MAPA) +
geom_density2d(data = bcn_reclamos,
aes(x = LONGITUD, y = LATITUD, color=stat(level))) +
scale_color_viridis_c() +
labs(title = "Densidad de reclamos",
subtitle = "Barcelona",
x = "Longitud",
y = "Latitud",
color = "Cantidad",
caption = "Fuente: Ajuntament de Barcelona")
Vemos con mayor claridad que la mayor cantidad de observaciones se da en el barrio de Sant Antoni, que alcanza el color amarillo en la escala viridis. Luego existen otros puntos que se destacan en la ciudad, y decrecen su valor a medida que se acercan a los límites de la ciudad.
Visualicemos entonces un facetado de las categorías vistas anteriormente:
ggmap(MAPA) +
geom_point(data = filter(bcn_reclamos, TIPUS %in% reclamos_frecuentes),
aes(x = LONGITUD, y = LATITUD, color = TIPUS),
size = 0.1, alpha = 0.1) +
guides(color = guide_legend(override.aes = list(size=2, alpha = 1))) +
scale_color_brewer(palette = "Set1") +
facet_wrap(~TIPUS) +
labs(title = "Facetado de tipos de reclamos",
subtitle = "Barcelona",
x = "Longitud",
y = "Latitud",
color = "Tipo",
caption = "Fuente: Ajuntament de Barcelona")
¿Que pasó con Consultas? Al filtrar las observacines que no tenían coordenadas, todas las observaciones de la categoría Consultas desaparecieron. Al mirar con atención el dataset original vemos que el canal por el cual se hicieron todas estas Consultas es por la Web y suponemos no debe ser necesario, al tratarse solo de una Consulta y no de un reclamo puntual, de establecer ninguna dirección. Respecto a los otros tipos de reclamo, en general vemos que la distribución es más bien homogenea. En el caso de Petición de Servicio la cantidad es considerablemente menor al de los otros tipos de reclamo y, además, sí se reconoce mayor concentración el centro de la ciudad. En cambio en Incidenca, Quejas y Sugerencias alcanza todo el territorio de forma más pareja.
Para hacer las diferencias aún mas nítidas, podemos facetar con la estimación de densidad Kensel:
ggmap(MAPA) +
geom_density2d(data = filter(bcn_reclamos, TIPUS %in% reclamos_frecuentes),
aes(x = LONGITUD, y = LATITUD, color = stat(level)))+
scale_color_viridis_c() +
facet_wrap(~TIPUS) +
labs(title = "Facetado de densidad por tipos de reclamos",
subtitle = "Barcelona",
x = "Longitud",
y = "Latitud",
color = "Cantidad",
caption = "Fuente: Ajuntament de Barcelona")
## Warning: Computation failed in `stat_density2d()`:
## missing value where TRUE/FALSE needed
Vemos de forma más clara como varían las variaciones del patrón espacial de los datos elegidos. Si bien Incidencia Sugerencia y Queja se parecen un poco, la categoría de Petición de Servicios es considerablemente distinta a la de las demás.
Comparemos dos tipos de reclamo (Sugerencia y Queja) mostrando dónde ocurren en cada día de la semana.
bcn_reclamos <- bcn_reclamos %>%
mutate(dia_semana = wday(fecha_alta, label = TRUE))
ggmap(MAPA) +
geom_point(data = filter(bcn_reclamos,
TIPUS %in% c("SUGGERIMENT", "QUEIXA")),
aes(x = LONGITUD, y = LATITUD, color = TIPUS), alpha = .4, size = .1) +
guides(color = guide_legend(override.aes = list(size=2, alpha = 1))) +
facet_wrap(~dia_semana, nrow = 2) +
labs(title = "Facetado de 2 tipos de reclamos",
subtitle = "Barcelona",
x = "Longitud",
y = "Latitud",
color = "Tipo",
caption = "Fuente: Ajuntament de Barcelona")
Se ve claramente la disminución de las observaciones durante el fin de semana. Pero espacialmente no se llega a detectar un patrón específico.
Mejor concentrmosnos en un tipo de reclamo en particular y evaluemos en que zonas se concentra de acuerdo al día de la semana:
ggmap(MAPA) +
geom_density2d(data = filter(bcn_reclamos, TIPUS %in% "QUEIXA"),
aes(x = LONGITUD, y = LATITUD, color=stat(level))) +
scale_color_viridis_c() +
facet_wrap(~dia_semana, nrow = 2) +
labs(title = "Concentración espacial de Sugerencias",
subtitle = "Barcelona, según día de la semana",
x = "Longitud",
y = "Latitud",
color = "Cantidad",
caption = "Fuente: Ajuntament de Barcelona")
Vemos que la mayor concentración espacial es el día jueves en una zona alejada del centro, cosa que se mantiene el día viernes pero en menor intensidad. En cambio el resto de los días la mayor concentración se encuentra del lado opuesta de la ciudad, alcanzando su pico el día martes.