Módulo 1: Geoprocesamiento

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()
  1. Del mismo portal de datos elegirán un dataset con registros geo-referenciados. Por ejemplo, las escuelas de la ciudad (o las comisarías, o las propiedades en alquiler) con sus coordenadas. Elegimos un dataset que contiene los museos y bibliotecas:
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="")

  1. Realizando un join espacial, asignar a cada registro geo-referenciado el barrio/distrito que le corresponde:

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
  1. Utilizando ggplot():
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

Módulo 2: Acceso a información urbana georeferenciada en repositorios online

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/RtmpR39trf/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 244948 points
##             $osm_lines : 'sf' Simple Features Collection with 45960 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")

  1. Descargar de OpenStreetMap una (o más) capas de datos de tipo puntos o polígonos.

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() 
    1. Proyectar los datos descargados en un mapa y comentar los resultados: ¿Cómo se distribuyen en la Ciudad?
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

    1. Hacer un conteo de los ítems de la capa descargada por barrio, mapearlo y compararlo con el conteo de los ítems descargados en el ejercicio anterior: ¿La distribución es similar o hay diferencias? ¿A qué se puede deber?

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.60  
##  05     :1                     3rd Qu.:17.25  
##  06     :1                     Max.   :31.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.

Módulo 3: Descargando y analizando datos de redes sociales: Twitter

Activemos este paquete para interactuar con Twitter.

library(rtweet)
## 
## Attaching package: 'rtweet'
## The following object is masked from 'package:purrr':
## 
##     flatten

I. Descargar tweets que se originen en los alrededores de la Ciudad con la que están trabajando, y explorar las columnas/variables que contiene.

Como no obtuvimos la autorización de Twitter, utilizaremos un dataset de la Región Metropolitana de Buenos Aires:

Tweets_rmba <- read.csv("Clase 8_tweets_rmba.csv")

Ahora quedémosnos sólo con el 50% de las observaciones y filtremos las que provengan de la fuente Twitter, excluyendo las de Instagram y otras redes sociales:

Tweets_rmba <- sample_frac(Tweets_rmba, 0.5) %>% 
filter(str_detect(source, "Twitter"))
names(Tweets_rmba)
##  [1] "X"                     "Y"                     "id"                   
##  [4] "in_reply_to_status_id" "in_reply_to_user_id"   "text"                 
##  [7] "created"               "lang"                  "source"               
## [10] "user_name"             "user_id"               "user_created"         
## [13] "user_description"      "user_location"         "user_followers"       
## [16] "user_followed"

Vemos que el dataset solo tiene 16 variables, de las cuales se destacan las coordenadas (x e y), el Id y nombre de usuario, el contenido del Tweet y la ubicación, cantidad de seguidores y seguidos del usuario.

  1. Analizar:
  1. ¿Cuáles son los mensajes con más repercusión? ¿Qué dicen?

Como el dataset no contiene la cantidad de retweets, ni likes, reformulemos la pregunta: ¿Cuáles son los 10 lugares donde más twitteó la gente?

  ggplot(Tweets_rmba) +
  geom_bar(aes(user_location)) + 
    coord_flip() +
     labs(title = "Procedencia de los usuarios",
          x = "Cantidad",
          y = "Ubicación")

Dado que la variable “user_location” refleja el texto que cada usuario eligió para describir su ubicación (no de las coordenadas de origen del tweet) las variabilidad es grande. Algunos eligen su verdadera ubicación y otros se ponen creativos: “For now: Vicente Lopez” o “No Te Va Gustar,LVP y La Beriso, mis bandas queridas”.

Probemos extraer el top 10 de lugares más frecuentes, eliminando los tweets de usuarios sin “user_location”:

Tweets_rmba %>%
    filter(user_location != "", !is.na(user_location)) %>% 
    count(user_location) %>% 
    top_n(10, n) %>% 
    ggplot() +
      geom_col(aes(x = reorder(user_location, n), y = n), fill="salmon") +
      coord_flip() +
      labs(title = "Procedencia de los usuarios",
           x = "Ubicación",
           y = "Cantidad")

Vemos que las ubicaciones más utilizadas son Buenos Aires, Argentina, Ramos Mejía, La Plata y la Ciudad de Buenos Aires.

  1. ¿En qué momento del día se realiza la mayor cantidad de tweets? Graficar.

Primero lo transformaremos al formato fecha. Luego filtraremos los tweets realizados en un día determinado (01/06/2018) y grafiquemos por horas:

library(lubridate)
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:dplyr':
## 
##     intersect, setdiff, union
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
Tweets_rmba_0106 <-Tweets_rmba %>% 
  mutate(created=ymd_hms(created)) %>% 
  filter(str_detect(created,"2018-06-01"))

ts_plot(Tweets_rmba_0106, "hours") +
  labs(title = "Distribución de Tweets 01/06/2018",
          x = "Horario",
          y = "Cantidad")

En el gráfico podemos observar la cantidad de tweets distribuídos a lo largo del día 01/06/2018, en el cual se puede observar el pico a las 15:00hs. A su vez, podemos observar la ausencia de tweets a partir de las 18:00hs.

  1. ¿Cómo se distribuye la popularidad de los usuarios? ¿Quiénes son los 5 que más seguidores tienen? Graficar.

Veamos los usuarios más populares (según la cantidad de seguidores):

ggplot(Tweets_rmba) +
    geom_histogram(aes(x = user_followers), bins = 30, fill = "salmon", color = "salmon") + 
          labs(title = "Usuarios según cantidad de seguidores",
          x = "Usuarios",
          y = "Cantidad de Seguidores")

La distribución es de tipo “power law” típica en los rankings de popularidad. Esto demuestra una enorme masa de usuarios con popularidad mínima y un número muy pequeño de usuarios con una gran cantidad de seguidores.

Ahora veámoslo en escala logarítmica:

ggplot(Tweets_rmba) +
    geom_histogram(aes(x = user_followers), bins = 30, fill = "salmon", color = "salmon") +
    scale_x_log10() + 
    labs(title = "Usuarios según cantidad de seguidores",
         subtitle = "en escala logarítmica",
          x = "Usuarios",
          y = "Cantidad de Seguidores")
## Warning: Transformation introduced infinite values in continuous x-axis
## Warning: Removed 191 rows containing non-finite values (stat_bin).

Obtengamos un top 5 de los usuarios más populares, su location, y el contenido del tweet:

Tweets_rmba %>% 
    top_n(5, user_followers) %>% 
    arrange(desc(user_followers)) %>% 
    select(user_name, user_followers, user_location, text) 
##       user_name user_followers           user_location
## 1 eltreceprensa         726578               Argentina
## 2    waldonavia         116935       Argentina-Uruguay
## 3  crescentegus          76534 Buenos Aires, Argentina
## 4  crescentegus          76530 Buenos Aires, Argentina
## 5   SamantaCaso          66885 Buenos Aires, Argentina
## 6   SamantaCaso          66885 Buenos Aires, Argentina
##                                                                                                                                         text
## 1      Primeras imágenes de la incorporación de\n@osvaldolaportok a @lasestrellas en un rol clave #MarioEstrella cc… https://t.co/44hchsg66M
## 2 Buen día!!! Aquí estamos en Family Pets!!! De todo para ellos porque son Familia!!! En Instagram nos encontras en… https://t.co/6j7HUTijG6
## 3                                                                                                        Siga todos que FAV e RT esse tweet!
## 4                                                                                               Follow everyone who retweets and likes this‼️
## 5                                       \U0001f433\U0001f31e\U0001f3ca\U0001f3fb‍♀️\U0001f459\nhttps://t.co/6KJPNaIyRN https://t.co/8v9DMOsLWk
## 6                                                                                                   Snack \U0001f433 https://t.co/hVN3G0HqVy
  1. Crear mapas que muestren posición de los tweets y cantidad de seguidores del usuario que tuitea:
library(ggmap)
## Google's Terms of Service: https://cloud.google.com/maps-platform/terms/.
## Please cite ggmap if you use it! See citation("ggmap") for details.

Antes que nada filtremos los tweets que no tienen coordenadas.

Tweets_rmba <- Tweets_rmba %>% 
    filter(!is.na(X), !is.na(Y))

Y definamos la bounding box de los tweets para poder mapear:

bboxtweets_Tweets_rmba <- make_bbox(lon = Tweets_rmba$X, lat = Tweets_rmba$Y)

bboxtweets_Tweets_rmba
##      left    bottom     right       top 
## -59.32611 -35.34362 -57.78626 -33.88824

Definamos el mapa base segun las coordenadas obtenidas y grafiquemos las observaciones:

mapa_Tweets_rmba <- get_stamenmap(bboxtweets_Tweets_rmba, zoom = 10)
## Source : http://tile.stamen.com/terrain/10/343/614.png
## Source : http://tile.stamen.com/terrain/10/344/614.png
## Source : http://tile.stamen.com/terrain/10/345/614.png
## Source : http://tile.stamen.com/terrain/10/346/614.png
## Source : http://tile.stamen.com/terrain/10/347/614.png
## Source : http://tile.stamen.com/terrain/10/343/615.png
## Source : http://tile.stamen.com/terrain/10/344/615.png
## Source : http://tile.stamen.com/terrain/10/345/615.png
## Source : http://tile.stamen.com/terrain/10/346/615.png
## Source : http://tile.stamen.com/terrain/10/347/615.png
## Source : http://tile.stamen.com/terrain/10/343/616.png
## Source : http://tile.stamen.com/terrain/10/344/616.png
## Source : http://tile.stamen.com/terrain/10/345/616.png
## Source : http://tile.stamen.com/terrain/10/346/616.png
## Source : http://tile.stamen.com/terrain/10/347/616.png
## Source : http://tile.stamen.com/terrain/10/343/617.png
## Source : http://tile.stamen.com/terrain/10/344/617.png
## Source : http://tile.stamen.com/terrain/10/345/617.png
## Source : http://tile.stamen.com/terrain/10/346/617.png
## Source : http://tile.stamen.com/terrain/10/347/617.png
## Source : http://tile.stamen.com/terrain/10/343/618.png
## Source : http://tile.stamen.com/terrain/10/344/618.png
## Source : http://tile.stamen.com/terrain/10/345/618.png
## Source : http://tile.stamen.com/terrain/10/346/618.png
## Source : http://tile.stamen.com/terrain/10/347/618.png
## Source : http://tile.stamen.com/terrain/10/343/619.png
## Source : http://tile.stamen.com/terrain/10/344/619.png
## Source : http://tile.stamen.com/terrain/10/345/619.png
## Source : http://tile.stamen.com/terrain/10/346/619.png
## Source : http://tile.stamen.com/terrain/10/347/619.png
ggmap(mapa_Tweets_rmba) +
    geom_point(data = Tweets_rmba, aes(x = X, y = Y), color = "salmon", alpha=.5) +  labs(title = "Tweets en la RMBA",
          x = "Longitud",
          y = "Latitud")

Dada la gran cantidad de Tweets, graficaremos solo las que ocurrieron el día 01/06 de 2018. Volvamos a definir la bounding box de los tweets ocurridos en esa fecha:

bboxtweets_Tweets_rmba_0106 <- make_bbox(lon = Tweets_rmba_0106$X, lat = Tweets_rmba_0106$Y)

bboxtweets_Tweets_rmba_0106
##      left    bottom     right       top 
## -58.94038 -34.97769 -57.92611 -34.40365

Definamos la base segun las coordenadas obtenidas y grafiquemos las observaciones:

mapa_Tweets_rmba_0106_terrainlines <- get_stamenmap(bboxtweets_Tweets_rmba_0106, maptype = "terrain-lines", zoom = 11)
## Source : http://tile.stamen.com/terrain-lines/11/688/1232.png
## Source : http://tile.stamen.com/terrain-lines/11/689/1232.png
## Source : http://tile.stamen.com/terrain-lines/11/690/1232.png
## Source : http://tile.stamen.com/terrain-lines/11/691/1232.png
## Source : http://tile.stamen.com/terrain-lines/11/692/1232.png
## Source : http://tile.stamen.com/terrain-lines/11/693/1232.png
## Source : http://tile.stamen.com/terrain-lines/11/694/1232.png
## Source : http://tile.stamen.com/terrain-lines/11/688/1233.png
## Source : http://tile.stamen.com/terrain-lines/11/689/1233.png
## Source : http://tile.stamen.com/terrain-lines/11/690/1233.png
## Source : http://tile.stamen.com/terrain-lines/11/691/1233.png
## Source : http://tile.stamen.com/terrain-lines/11/692/1233.png
## Source : http://tile.stamen.com/terrain-lines/11/693/1233.png
## Source : http://tile.stamen.com/terrain-lines/11/694/1233.png
## Source : http://tile.stamen.com/terrain-lines/11/688/1234.png
## Source : http://tile.stamen.com/terrain-lines/11/689/1234.png
## Source : http://tile.stamen.com/terrain-lines/11/690/1234.png
## Source : http://tile.stamen.com/terrain-lines/11/691/1234.png
## Source : http://tile.stamen.com/terrain-lines/11/692/1234.png
## Source : http://tile.stamen.com/terrain-lines/11/693/1234.png
## Source : http://tile.stamen.com/terrain-lines/11/694/1234.png
## Source : http://tile.stamen.com/terrain-lines/11/688/1235.png
## Source : http://tile.stamen.com/terrain-lines/11/689/1235.png
## Source : http://tile.stamen.com/terrain-lines/11/690/1235.png
## Source : http://tile.stamen.com/terrain-lines/11/691/1235.png
## Source : http://tile.stamen.com/terrain-lines/11/692/1235.png
## Source : http://tile.stamen.com/terrain-lines/11/693/1235.png
## Source : http://tile.stamen.com/terrain-lines/11/694/1235.png
## Source : http://tile.stamen.com/terrain-lines/11/688/1236.png
## Source : http://tile.stamen.com/terrain-lines/11/689/1236.png
## Source : http://tile.stamen.com/terrain-lines/11/690/1236.png
## Source : http://tile.stamen.com/terrain-lines/11/691/1236.png
## Source : http://tile.stamen.com/terrain-lines/11/692/1236.png
## Source : http://tile.stamen.com/terrain-lines/11/693/1236.png
## Source : http://tile.stamen.com/terrain-lines/11/694/1236.png
ggmap(mapa_Tweets_rmba_0106_terrainlines) +
    geom_point(data = Tweets_rmba_0106, aes(x = X, y = Y), color = "red", alpha=.5) +
          labs(title = "Tweets en la RMBA",
               subtitle = "01/06/2018",
          x = "Longitud",
          y = "Latitud")

También probemos colorear según la popularidad del usuario:

ggmap(mapa_Tweets_rmba_0106_terrainlines) + 
    geom_point(data = Tweets_rmba_0106, 
               aes(x = X, y = Y, color = user_followers)) +
    scale_color_distiller(palette = "Spectral") +
    labs(title = "Tweets en la RMBA segun popularidad del usuario",
         subtitle = "01/06/2018",
         color = "Seguidores",
         x = "Longitud",
         y = "Latitud")

A continuación haremos mapas interactivos con leaflet:

library(leaflet)

Renombremos las variables que contienen las coordenadas para que el leaflet nos la reconozca:

Tweets_rmba_0106 <- Tweets_rmba_0106 %>% 
  rename(longitude = X) %>% 
  rename(latitude = Y)

Y ahora grafiquemos:

leaflet(Tweets_rmba_0106) %>% 
    addTiles() %>%
    addMarkers()
## Assuming "longitude" and "latitude" are longitude and latitude, respectively

Agreguemos “popup” para ver el texto en cada tweet cliqueando sobre el pin:

leaflet(Tweets_rmba_0106) %>% 
    addTiles() %>% 
    addMarkers(popup = ~text)
## Assuming "longitude" and "latitude" are longitude and latitude, respectively

Ahora usemos el color para indicar la cantidad de seguidores del autor de cada tweet. Primero definamos la paleta:

paleta <- colorNumeric(
  palette = "viridis",
  domain = Tweets_rmba_0106$user_followers)

Y luego la usamos en nuestro mapa:

leaflet(Tweets_rmba_0106) %>% 
    addTiles() %>% 
    addCircleMarkers(popup = ~text,
                     color = ~paleta(user_followers))
## Assuming "longitude" and "latitude" are longitude and latitude, respectively

Por último agreguemos una leyenda que explique la codificación de los datos.

leaflet(Tweets_rmba_0106) %>% 
    addTiles() %>% 
    addCircleMarkers(popup = ~text,
                     color = ~paleta(user_followers)) %>% 
    addLegend(title = "Seguidores", pal = paleta, values = ~user_followers)
## Assuming "longitude" and "latitude" are longitude and latitude, respectively