library(tidyverse)
## ── Attaching packages ──────────────────────────────────────── tidyverse 1.2.1 ──
## ✔ ggplot2 3.2.0     ✔ purrr   0.3.2
## ✔ tibble  2.1.3     ✔ dplyr   0.8.3
## ✔ tidyr   0.8.3     ✔ stringr 1.4.0
## ✔ readr   1.3.1     ✔ forcats 0.4.0
## ── Conflicts ─────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
library(rtweet)
## 
## Attaching package: 'rtweet'
## The following object is masked from 'package:purrr':
## 
##     flatten
# El nombre que le asgnamos a la app en el formulario de autorización
appname <- "Mavegani"
## consumer key (en el ejemplo no es una clave real, usar la verdadera)
consumer_key <- "2LBxjw9MlI2WykC4mHEpXM71i"
## consumer secret (en el ejemplo no es un clave real, usar la verdadera)
consumer_secret <- "m7xJqnUP3LhbWcEjWbZcSWypfqZxF2DWKY4hd78hA2gJKAzCQt"

Ahora caputuraremos twits del Partido de Escobar sobre “elecciones” y “PASO”

library(tidyverse)
library(rtweet)
tweets_elecciones <- search_tweets(q = "elecciones OR PASO",
              geocode = "-34.342927,-58.777675,20mi",
              include_rts = FALSE,
              n = 100000,
              retryonratelimit = TRUE)
## retry on rate limit...
## waiting about 2 minutes...

Primero creamos una función que extrae los valores de lat y long del campo problemático:

coordenadas <- function(campo_coordenadas) {
    extraer_coordenadas <- function(lista_coords) {
        data_frame(lon = lista_coords[1],
                   lat = lista_coords[2])
    }
    
    map_df(campo_coordenadas, extraer_coordenadas)
}

Y con una cadena de funciones extraemos los datos de georeferenciamiento, los agregamos al dataframe en sus propias columnas, y por último descartamos los campos en formato lista:

tweets_elecciones <- tweets_elecciones %>% 
    cbind(coordenadas(tweets_elecciones$coords_coords)) %>% 
    select(-geo_coords, -coords_coords, -bbox_coords) 
## Warning: `data_frame()` is deprecated, use `tibble()`.
## This warning is displayed once per session.

Para empezar, filtramos nuestros tweets para conservar sólo los que contienen coordenadas exactas de posición.

tweets_elecciones_geo <- tweets_elecciones %>% 
    filter(!is.na(lat), !is.na(lon))
  1. ¿Cuáles son los mensajes con más repercusión? ¿Qué dicen?

Para obtener los tweets mas populares debemos obtenerlos en base a la cantidad de retweets que recibieron. Nos quedamos sólo con los tweets originales, descartando los que son retweets en si mismos (“is_retweet == TRUE”), y revisamos la distribución de sus retweets:

ggplot(filter(tweets_elecciones, !is_retweet))+
    geom_histogram(aes(x = retweet_count))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

El gráfico muestra una distribución de “power law”, típica en los rankings de popularidad. La mayoria de usuarios de Escobar posee una popularidad mínima que no supera los 500 seguidores.

Obtenemos un top 5 de los usuarios más populares de Escobar:

tweets_elecciones %>% 
    filter(!is_retweet) %>% 
    filter(retweet_count == max(retweet_count)) %>% 
    select(screen_name, retweet_count, followers_count,geocode = location, text)

Teniendo en cuenta a Escobar y el término elecciones como los motores de búsqueda iniciales. El usuario j7dios2018 es el de mayor popularidad teniendo 696 seguidores y su tweet mas rt fue “Los venezolanos que vinieron a vivir a Argentina escapando de venezuela despues de estas elecciones https://t.co/fpIN446PRr

  1. ¿En qué momento del día se realiza la mayor cantidad de tweets? Graficar.
ts_plot(tweets_elecciones, "days")

Según el gráfico el día en donde ocurre mayor cantidad de twits fue entre el 10 al 13 de octubre siendo el 11 de agosto el día de las PASO.

  1. ¿Cómo se distribuye la popularidad de los usuarios? ¿Quiénes son los 5 que más seguidores tienen? Graficar.
users_data(tweets_elecciones) %>% head()
tweets_elecciones %>%
  ggplot() +
  geom_bar(aes(location)) + 
    coord_flip() +
     labs(title = "Procedencia de los usuarios",
          x = "cantidad",
          y = "ubicación")

tweets_elecciones %>%
    filter(location != "", !is.na(location)) %>% 
    count(location) %>% 
    top_n(10, n) %>% 
    ggplot() +
      geom_col(aes(x = reorder(location, n), y = n)) + 
      coord_flip() +
      labs(title = "Procedencia de los usuarios",
           x = "ubicación",
           y = "cantidad")

Aquí se puede analizar que pese a establecer a escobar como partido de búsqueda, la mayoría de los twits provenían de otros partidos, siendo la mayoría de Tigre y San Isidro.

Aislando los tweets que poseen coordenadas geográficas (lat y long), crear mapas que muestren posición de los tweets y cantidad de seguidores del usuario que tuitea.

Para empezar, filtramos nuestros tweets para conservar sólo los que contienen coordenadas exactas de posición.

tweets_elecciones_geo <- tweets_elecciones %>% 
    filter(!is.na(lat), !is.na(lon))

El resultado evidencia que lso tweets georeferenciados son sólo una pequeña fracción del total que se produce:

nrow(tweets_elecciones_geo)
## [1] 64
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.

Cuando disponemos de un dataframe con columnas de lat y long, obtener la bounding box es bastante fácil:

bbox <- c(min(tweets_elecciones_geo$lon),
          min(tweets_elecciones_geo$lat),
          max(tweets_elecciones_geo$lon),
          max(tweets_elecciones_geo$lat))

Lo descargamos así, entregando la bounding box del área que nos interesa:

mimapa <- get_stamenmap(bbox)
## 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/344/616.png
## Source : http://tile.stamen.com/terrain/10/345/616.png
## Source : http://tile.stamen.com/terrain/10/344/617.png
## Source : http://tile.stamen.com/terrain/10/345/617.png
ggmap(mimapa)

mapa_BA <- get_stamenmap(bbox, maptype = "toner-lite")
## Source : http://tile.stamen.com/toner-lite/10/344/615.png
## Source : http://tile.stamen.com/toner-lite/10/345/615.png
## Source : http://tile.stamen.com/toner-lite/10/344/616.png
## Source : http://tile.stamen.com/toner-lite/10/345/616.png
## Source : http://tile.stamen.com/toner-lite/10/344/617.png
## Source : http://tile.stamen.com/toner-lite/10/345/617.png
ggmap(mapa_BA)

También podemos asignar a cada punto un color de acuerdo a la popularidad del usuario:

ggmap(mapa_BA) + 
    geom_point(data = tweets_elecciones_geo, 
               aes(x = lon, y = lat, color = followers_count)) +
    scale_color_distiller(palette = "Spectral")

Por último, usemos el tamaño de cada punto para indicar la repercusión de cada tweet:

ggmap(mapa_BA) + 
    geom_point(data = tweets_elecciones_geo, 
               aes(x = lon, y = lat, color = followers_count, size = retweet_count),
               alpha = .5) +
    scale_color_distiller(palette = "Spectral")

Por último, usemos el tamaño de cada punto para indicar la repercusión de cada tweet:

ggmap(mapa_BA) + 
    geom_point(data = tweets_elecciones_geo, 
               aes(x = lon, y = lat, color = followers_count, size = retweet_count),
               alpha = .5) +
    scale_color_distiller(palette = "Spectral")

Mapas interactivos con leaflet

library(leaflet)
leaflet(tweets_elecciones_geo) 

Falta que aparezcan nustros datos.

con addMarkers() leaflet se encarga de buscar las coordenadas de cada observación, y si aparecen con algún nombre esperable, las identifica y sitúa en el mapa un pin por cada una.

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

Para mejorarlo, agregamos la opción de “popup”, que permite extraer información adicional cliqueando sobre un pin.

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

Qué dicen?

Si en vez de pines usamos círculos vía addCircleMarkers(), podemos controlar el diámetro del círculo que representa a un tweet para mostrar su impacto, de acuerdo a la cantidad de retweets que recibió:

leaflet(tweets_elecciones_geo) %>% 
    addTiles() %>% 
    addCircleMarkers(radius = ~retweet_count,
                     popup = ~text)
## Assuming "lon" and "lat" are longitude and latitude, respectively

En el caso anterior no se observa un impacto importante en ninguna localidad a en los tweets en base a el impacto de los retweet que recibieron.

paleta <- colorNumeric(
  palette = "magma",
  domain = tweets_elecciones_geo$followers_count)

Podemos usar el color para indicar la cantidad de seguidores del autor de cada tweet. A partir del mapa anterior se puede observar que la mayoría de los autores no posee más de 2000 seguidores. Siendo que en Campana se encuentra el único autor de un tweet que podría tener más de 6mil seguidores:

leaflet(tweets_elecciones_geo) %>% 
    addTiles() %>% 
    addCircleMarkers(radius = ~retweet_count,
                     popup = ~text,
                     color = ~paleta(followers_count))
## Assuming "lon" and "lat" are longitude and latitude, respectively

Como siempre es muy util agregar una leyenda que explique la codificación de los datos. leaflet sólo permite mostrar leyendas basadas en color (no en el diamétro de los círculos), pero algo es algo. Agregamos la leyenda así:

leaflet(tweets_elecciones_geo) %>% 
    addTiles() %>% 
    addCircleMarkers(radius = ~retweet_count,
                     popup = ~text,
                     color = ~paleta(followers_count)) %>% 
    addLegend(title = "seguidores", pal = paleta, values = ~followers_count)
## Assuming "lon" and "lat" are longitude and latitude, respectively

Gracias a la función “popup”, que permite extraer información adicional cliqueando sobre un pin.