Las Redes Sociales (Twitter, Facebook, Instagram, etc.) son una fuente de información muy valiosa a la hora de hacer análisis enfocados en temas sociales ya que nos permiten conocer un poco más a los usuarios y los lazos/relaciones que existen entre ellos. Esto es una gran oportunidad para la ciencia de datos ya que a partir de algunas herramientas de minería de datos, se pueden descargar y monitorear tweets de diversas temáticas de interés.
A continuación descargaremos y analizaremos datos de la red social Twitter a partir de la conexión a su API (interfaz de programación de aplicaciones). Pero esta fuente de información también puede traer algunos dolores de cabeza, ya que por un lado, es probable que nos encontremos con que los datos tienen alguna “suciedad” o inconsistencia. Y por el otro lado, hay que decidir bien que información queremos descargar ya que la API de Twitter limita la cantidad de consultas a los tweets publicados en los últimos 7 días, y no nos permite descargar más de 18000 tweets por consulta.
Para poder descargar datos desde la API de Twitter, vamos a tener que cumplir con una serie de “requisitos”:
Tener un usuario/cuenta de Twitter. Caso contrario, deberán crearlo desde el siguiente link: https://twitter.com/i/flow/signup
Crear una cuenta de developer en Twitter asociada al usuario del punto 1: https://developer.twitter.com/en/apply-for-access Al momento de crear esta cuenta, Twitter nos va a pedir que completemos una serie de datos que luego analizarán para decidir si nos van a dar autorización al uso de su API. Cabe destacar que si completamos correctamente el formulario hay muy poca probabilidad de que Twitter rechace nuestro pedido.
Una vez que tengamos la autorización podremos crear las “apps” que nos permitirán descargar datos. Aquí es donde accederemos a los 4 “códigos” importantes que nos solicita la API: Consumer Key, Consumer Secret, Access Token y Access Token Secret. Copiémoslos y peguémoslos en el siguiente chunk:
# Dato 1: Nombre que le pusimos a la app en el form de autorización de Twitter
appname <- "nombre_app"
# Dato 2: Consumer key que nos dio Twitter al autorizarnos
consumer_key <- "secuencia_de_caracteres_de_nuestra_consumer_key"
# Dato 3: Consumer secret que nos dio Twitter al autorizarnos
consumer_secret <- "secuencia_de_caracteres_de_nuestra_consumer_secret"
# Dato 4: Access Token que nos dio Twitter al autorizarnos
access_token <- "secuencia_de_caracteres_de_nuestro_access_token"
# Dato 5: Access Secret que nos dio Twitter al autorizarnos
access_secret <- "secuencia_de_caracteres_de_nuestro_access_secret"
Ahora si, comencemos activando nuestras ya conocidas librerías tidyverse
y ggmap
e instalemos y activemos rtweet
que nos permitirá descargar y analizar los datos de Twitter, y leaflet
que nos permitirá desarrollar mapas interactivos:
#install.packages("tidyverse")
library(tidyverse)
#install.packages("ggmap")
library(ggmap)
#install.packages("rtweet")
library(rtweet)
#install.packages("leaflet")
library(leaflet)
Ahora activemos el token que nos permitirá acceder a los datos ejecutando el siguiente chunk, que se nutrirá de los datos que cargamos previamente:
#twitter_token <- create_token(app = appname,
# consumer_key = consumer_key,
# consumer_secret = consumer_secret,
# access_token = access_token,
# access_secret = access_secret)
Si todo va bien, se les abrirá una ventana que les solicitará acceso a Twitter en el navegador donde deberán Aceptar. Y ahora si, ya estamos en condiciones de hacer nuestra primer descarga de datos con la función search_tweets()
, donde tendremos que ajustar algunos parámetros:
q = es el parámetro donde cargaremos los criterios de búsqueda que pueden ser palabras claves, usuarios o hashtags. En el caso de usar 2 o más criterios se podrá asignar condiciones como AND o OR, haciendo referencia a si ambos criterios tienen que estar o no en el mismo tweet. Cabe destacar que si las palabras claves que queremos buscar son compuestas debemos agregar un + entre ellas, por ejemplo “HOSPITAL+PUBLICO” ya que si no agregamos el signo, se descargaran tweets que tienen ambas palabras pero en cualquier lugar del texto.
n = es el parámetro donde asignamos la cantidad máxima de tweets que queremos descargar. Esto es importante ya que, cuanto más tweets descarguemos, más tiempo se demorará y además debemos tener en cuenta que cada llamada a la API puede descargar un límite de 18000 tweets.
lang = es el parámetro donde elegimos que idioma queremos los tweets. Por ejemplo “es” es para español y “en” es para inglés. Cabe destacar que este parámetro es opcional, es decir que si no lo escribimos, nos descargaremos tweets de todos los idiomas.
include_rts = es el parámetro donde decidimos si queremos descargar o no los RT que se hayan realizado.
Existen más parámetros opcionales, que podrán investigarlos desde el siguiente link: https://www.rdocumentation.org/packages/rtweet/versions/0.7.0/topics/search_tweets
Dicho todo esto, hagamos la primer búsqueda/descarga. En este caso nos descargamos todos los tweets relacionados a vacunación a partir del siguiente chunk:
#tweets_vacunacion <- search_tweets(q = "VACUNACION OR VACUNAS", #Palabras claves para la búsqueda
# n = 3100, #Cantidad máxima de Tweets que queremos descargar
# lang = "es", #Idioma de los tweets ("es" o "en")
# include_rts = FALSE) #FALSE si no queremos RT, sino TRUE
Pero a fines de poder seguir la clase en simultáneo y para poder replicar este manual con los mismos tweets, carguemos los que ya fueron descargados previamente ya que, si corren el chunk nuevamente se van a descargar otros tweets diferentes:
tweets_vacunacion <- readRDS(file = "tw_vacunacion_general.rds")
Como siempre, lo primero que vamos a chequear es la cantidad de filas y columnas:
dim(tweets_vacunacion)
## [1] 3100 90
Contamos con 3100 tweets y 90 columnas de información! Demasiadas variables, no? Veamos de que se tratan:
names(tweets_vacunacion)
## [1] "user_id" "status_id"
## [3] "created_at" "screen_name"
## [5] "text" "source"
## [7] "display_text_width" "reply_to_status_id"
## [9] "reply_to_user_id" "reply_to_screen_name"
## [11] "is_quote" "is_retweet"
## [13] "favorite_count" "retweet_count"
## [15] "quote_count" "reply_count"
## [17] "hashtags" "symbols"
## [19] "urls_url" "urls_t.co"
## [21] "urls_expanded_url" "media_url"
## [23] "media_t.co" "media_expanded_url"
## [25] "media_type" "ext_media_url"
## [27] "ext_media_t.co" "ext_media_expanded_url"
## [29] "ext_media_type" "mentions_user_id"
## [31] "mentions_screen_name" "lang"
## [33] "quoted_status_id" "quoted_text"
## [35] "quoted_created_at" "quoted_source"
## [37] "quoted_favorite_count" "quoted_retweet_count"
## [39] "quoted_user_id" "quoted_screen_name"
## [41] "quoted_name" "quoted_followers_count"
## [43] "quoted_friends_count" "quoted_statuses_count"
## [45] "quoted_location" "quoted_description"
## [47] "quoted_verified" "retweet_status_id"
## [49] "retweet_text" "retweet_created_at"
## [51] "retweet_source" "retweet_favorite_count"
## [53] "retweet_retweet_count" "retweet_user_id"
## [55] "retweet_screen_name" "retweet_name"
## [57] "retweet_followers_count" "retweet_friends_count"
## [59] "retweet_statuses_count" "retweet_location"
## [61] "retweet_description" "retweet_verified"
## [63] "place_url" "place_name"
## [65] "place_full_name" "place_type"
## [67] "country" "country_code"
## [69] "geo_coords" "coords_coords"
## [71] "bbox_coords" "status_url"
## [73] "name" "location"
## [75] "description" "url"
## [77] "protected" "followers_count"
## [79] "friends_count" "listed_count"
## [81] "statuses_count" "favourites_count"
## [83] "account_created_at" "verified"
## [85] "profile_url" "profile_expanded_url"
## [87] "account_lang" "profile_banner_url"
## [89] "profile_background_url" "profile_image_url"
Definitivamente son muchas! Podríamos estar bastante tiempo analizando que contiene cada una, así que hoy concentrémonos solo en las siguientes:
screen_name: nombre del usuario
followers_count: cantidad de seguidores del usuario
retweet_count: cantidad de RT que tuvo el tweet al momento de descargarlo
text: texto que se incluyó en el tweet
location: ubicación donde habita el usuario
coords_coords, bbox_coords y geo_coords: ubicación geográfica de donde se realizó el tweet (formato de lista)
Arranquemos con la primer interrogante: ¿Dónde habitan los usuarios que generaron los tweets que descargamos? Usemos ggplot()
para intentar responder:
ggplot(tweets_vacunacion) +
geom_bar(aes(x=location)) +
coord_flip() +
labs(title = "ORIGEN DE LOS USUARIOS",
x = "Cantidad",
y = "Ubicación")
Demasiada información! Este gráfico es muy difícil de entender. Probemos calculando solamente el top 20 de ubicaciones:
tweets_location <- tweets_vacunacion %>%
group_by(location) %>%
summarise(cantidad=n()) %>%
arrange(desc(cantidad)) %>%
head(20)
tweets_location
## # A tibble: 20 x 2
## location cantidad
## <chr> <int>
## 1 "" 1102
## 2 "Argentina" 63
## 3 "Venezuela" 58
## 4 "Buenos Aires, Argentina" 53
## 5 "Panamá" 46
## 6 "Ciudad Autónoma de Buenos Aire" 32
## 7 "Colombia" 31
## 8 "Caracas, Venezuela" 29
## 9 "Ecuador" 26
## 10 "México" 25
## 11 "Caracas - Venezuela" 19
## 12 "Lima, Peru" 18
## 13 "Buenos Aires" 17
## 14 "Honduras" 17
## 15 "Bogotá, D.C., Colombia" 16
## 16 "Costa Rica" 16
## 17 "Córdoba, Argentina" 15
## 18 "Dominican Republic" 15
## 19 "Quito, Ecuador" 12
## 20 "Guayaquil, Ecuador" 11
El campo location de la mayoría de los tweets (1102) está vacío, es decir que un 35% de los tweets fueron generados por usuarios que no registraron su ubicación. Esto lamentablemente es algo con lo que nos cruzaremos constantemente en este tipo de fuentes de datos.
Probemos nuevamente el gráfico de barras pero quitando los valores nulos de location:
ggplot(tweets_location %>%
filter(location!="")) +
geom_bar(aes(x = reorder(location, cantidad), weight=cantidad)) +
coord_flip() +
labs(title = "ORIGEN DE LOS USUARIOS",
x = "Ubicación",
y = "Cantidad")
Argentina es la ubicación que más usuarios declararon, seguida por Venezuela. Pero nótese que, como cada usuario carga manualmente la location, el campo puede estar un poco sucio ya que depende mucho de como escribe cada uno. Por ejemplo, Caracas aparece 2 veces: “Caracas, Venezuela” y “Caracas - Venezuela”. La diferencia es tan solo el “-” pero para R son 2 nombres diferentes.
Sigamos con el próximo interrogante: ¿Qué tan “populares” son los usuarios que generaron los tweets que descargamos? Hagamos un histograma para ver la distribución de la variable followers_count:
ggplot(tweets_vacunacion)+
geom_histogram(aes(x = followers_count)) +
labs(title = "POPULARIDAD DE LOS USUARIOS",
x = "Cantidad de Seguidores",
y = "Cantidad")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Hay muchas cuentas que tienen pocos seguidores y hay pocas cuentas que tienen muchos! Veamos cuales son y qué están diciendo las cuentas más populares que hablan del tema vacunación:
tweets_vacunacion %>%
arrange(desc(followers_count)) %>%
select(screen_name, followers_count, location, text) %>%
head(20)
## # A tibble: 20 x 4
## screen_name followers_count location text
## <chr> <int> <chr> <chr>
## 1 CNNEE 19792826 En todas par~ "¿Por qué Argentina guarda vacun~
## 2 NoticiasRCN 8113209 Colombia "Estados Unidos comprará 500 mil~
## 3 lopezdoriga 7839839 Ciudad de Mé~ "Estados Unidos asumiendo el lid~
## 4 la_patilla 7074207 Venezuela "Médicos Unidos de Venezuela exi~
## 5 la_patilla 7074207 Venezuela "Matan a dos policías de un equi~
## 6 la_patilla 7074207 Venezuela "Chavismo no paga, pero se reúne~
## 7 la_patilla 7074207 Venezuela "EEUU comprará 500 millones de v~
## 8 la_patilla 7074207 Venezuela "Maestros en Anzoátegui: Sin din~
## 9 ElNacionalWeb 5160308 Caracas - Ve~ "Pese a la poca transparencia y ~
## 10 ElNacionalWeb 5160308 Caracas - Ve~ "El proceso de vacunación contra~
## 11 ElNacionalWeb 5160308 Caracas - Ve~ "OPS asegura que proceso para en~
## 12 ElNacionalWeb 5160308 Caracas - Ve~ "#9Jun | Médicos Unidos exige qu~
## 13 ElNacionalWeb 5160308 Caracas - Ve~ "Vacunación en Venezuela sin pas~
## 14 ElNacionalWeb 5160308 Caracas - Ve~ "#9Jun | ¿Cómo recibir la convoc~
## 15 ElNacionalWeb 5160308 Caracas - Ve~ "#9Jun | OPS asegura que proceso~
## 16 ElNacionalWeb 5160308 Caracas - Ve~ "#9Jun | Alcalde en Táchira prio~
## 17 FraseSimple 4488752 Venezuela "¡Puede hacerse realidad! \U0001~
## 18 FraseSimple 4488752 Venezuela "#Coronavirus \U0001f637 | Covid~
## 19 NTN24 4446546 Continente A~ "\"Porros por vacunas\": la prop~
## 20 WRadioColomb~ 4226724 Colombia "#Internacional EE.UU. comprará ~
Por lejos, vemos que CNNE (CNN en Español), con 19.792.826 seguidores es la cuenta más popular de mi muestra de tweets.
¿Y cómo hacemos si queremos ver quienes son los “influencers” de Argentina que hablaron sobre vacunación? Bueno, agreguemos un filter()
:
tweets_vacunacion %>%
filter(location=="Argentina") %>%
arrange(desc(followers_count)) %>%
select(screen_name, followers_count, location, text) %>%
head(20)
## # A tibble: 20 x 4
## screen_name followers_count location text
## <chr> <int> <chr> <chr>
## 1 AgenciaTelam 669522 Argentina "Funcionarios destacan el avance del~
## 2 AgenciaTelam 669522 Argentina "\U0001f1e6\U0001f1f7\U0001f1ea\U000~
## 3 Guillodietri~ 509859 Argentina "Acompaño a su familia en este difíc~
## 4 minutounocom 401950 Argentina "Avanza el plan de vacunación: envía~
## 5 silviafbarrio 121565 Argentina "\U0001f4cc ATENCIÓN \U0001f4cc\nVac~
## 6 laderechadia~ 85228 Argentina "\U0001f1e6\U0001f1f7 | Alberto Fern~
## 7 gkatopodis 81180 Argentina "Gracias a todos y todas los que hac~
## 8 negocioscomar 64976 Argentina "Según el #CENE de la Universidad de~
## 9 IzquierdaWeb 48123 Argentina "Estados Unidos acopió vacunas y acu~
## 10 PoliticaClar~ 43425 Argentina "La trama secreta de cómo se incluyó~
## 11 PoliticaClar~ 43425 Argentina "Las contradicciones del Estado débi~
## 12 _IPNoticias 42481 Argentina "\U0001f489 El Monitor Público de Va~
## 13 Ar_Unida 29548 Argentina "¡Ya se aplicaron 15.279.488 vacunas~
## 14 wgoobar 28334 Argentina "Te invito a visitar mi canal Pandem~
## 15 EFabregat 26762 Argentina "Mientras leo gente indignadísima po~
## 16 prensaobrera 15091 Argentina "La lucha docente en CABA, entre la ~
## 17 prensaobrera 15091 Argentina "#CABA jornada de ollas y piquetes. ~
## 18 prensaobrera 15091 Argentina "En el marco de la jornada nacional ~
## 19 FFerrariOk 12380 Argentina "Vacunación anticovid continúa con e~
## 20 MonterosEva 11597 Argentina "Aaaah, bueh\U0001f926, gran nivel d~
Vemos que por lo general, las cuentas oficiales de los medios de comunicación de Argentina son quienes más seguidores tienen entre los usuarios que hablan de vacunación. Pero también vemos que aparecen algunos nombres conocidos de la política como el de Guillermo Dietrich o Gabriel Katopodis.
Ahora pasemos a analizar los tweets más populares: ¿Qué dicen los tweets de mi muestra que más RT tuvieron? Hagamos otro histograma para ver la distribución de la variable retweet_count:
ggplot(filter(tweets_vacunacion))+
geom_histogram(aes(x = retweet_count)) +
labs(title = "TWEET MÁS POPULARES",
x = "Cantidad de RT",
y = "Tweets")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
La mayoría de los tweets descargados tienen muy pocos RT (o ninguno), pero algunos superan los 150.
Veamos quién generó y que dice el tweet con más RT:
tweets_vacunacion %>%
filter(retweet_count == max(retweet_count)) %>%
select(screen_name, retweet_count, followers_count, location, text)
## # A tibble: 1 x 5
## screen_name retweet_count followers_count location text
## <chr> <int> <int> <chr> <chr>
## 1 mmbarrionue~ 173 35292 "" "El excelente ritmo de va~
El usuario que escribió el tweet más popular fue mmbarrionuevo, quién tiene 35292 seguidores y no declaró su ubicación. El mensaje que tuvo 173 RT fue:
“El excelente ritmo de vacunación en la Argentina. Más 2.200.000 argentinos vacunados cada 7 días, casi el 5% de la población en una semana. El desafío, como siempre, es seguir recibiendo y ahora produciendo vacunas para sostener el ritmo. Cuidados + Vacunas https://t.co/loz3ZnTsNO”
Hasta acá todavía no analizamos una variable muy importante para las redes sociales: la temporalidad! Si bien aquí podríamos utilizar todo nuestro conocimiento sobre lubridate
, gracias a que estamos trabajando con el paquete rtweet
no es necesario porque tiene la función ts_plot()
que nos permitirá manipular el tiempo de forma sencilla:
ts_plot(tweets_vacunacion, by="minutes") +
labs(title = "EVOLUCIÓN DE TWEETS RELACIONADOS A VACUNACIÓN",
x = "Hora",
y = "Tweets")
Podemos ver que el “pico” de tweets fue alrededor de las 22h.
Llegó el momento de sumergirnos en la cuestión espacial que tanto nos gusta! Recuerden que al principio habíamos visto que había 3 columnas que referían a ubicación geográfica, y justamente ahora es el momento de utilizarlas. Pero hay un detalle: estan guardados en formato “lista”, un formato específico en el que se descargan los datos geográficos de Twitter, y esto no nos va a permitira manipular esta información de la misma forma en la que lo veníamos haciendo.
Por lo tanto debemos aprender una función nueva llamada lat_lng()
que también es parte del el paquete rtweet
y que nos ayudará a extraer las coordanadas de cada uno de los tweets (siempre y cuando el usuario lo haya permitido):
tweets_vacunacion <- lat_lng(tweets_vacunacion, coords = c("coords_coords", "bbox_coords", "geo_coords"))
Si todo está bien, se deberían haber agregado 2 nuevas columnas: lat y lng
names(tweets_vacunacion)
## [1] "user_id" "status_id"
## [3] "created_at" "screen_name"
## [5] "text" "source"
## [7] "display_text_width" "reply_to_status_id"
## [9] "reply_to_user_id" "reply_to_screen_name"
## [11] "is_quote" "is_retweet"
## [13] "favorite_count" "retweet_count"
## [15] "quote_count" "reply_count"
## [17] "hashtags" "symbols"
## [19] "urls_url" "urls_t.co"
## [21] "urls_expanded_url" "media_url"
## [23] "media_t.co" "media_expanded_url"
## [25] "media_type" "ext_media_url"
## [27] "ext_media_t.co" "ext_media_expanded_url"
## [29] "ext_media_type" "mentions_user_id"
## [31] "mentions_screen_name" "lang"
## [33] "quoted_status_id" "quoted_text"
## [35] "quoted_created_at" "quoted_source"
## [37] "quoted_favorite_count" "quoted_retweet_count"
## [39] "quoted_user_id" "quoted_screen_name"
## [41] "quoted_name" "quoted_followers_count"
## [43] "quoted_friends_count" "quoted_statuses_count"
## [45] "quoted_location" "quoted_description"
## [47] "quoted_verified" "retweet_status_id"
## [49] "retweet_text" "retweet_created_at"
## [51] "retweet_source" "retweet_favorite_count"
## [53] "retweet_retweet_count" "retweet_user_id"
## [55] "retweet_screen_name" "retweet_name"
## [57] "retweet_followers_count" "retweet_friends_count"
## [59] "retweet_statuses_count" "retweet_location"
## [61] "retweet_description" "retweet_verified"
## [63] "place_url" "place_name"
## [65] "place_full_name" "place_type"
## [67] "country" "country_code"
## [69] "geo_coords" "coords_coords"
## [71] "bbox_coords" "status_url"
## [73] "name" "location"
## [75] "description" "url"
## [77] "protected" "followers_count"
## [79] "friends_count" "listed_count"
## [81] "statuses_count" "favourites_count"
## [83] "account_created_at" "verified"
## [85] "profile_url" "profile_expanded_url"
## [87] "account_lang" "profile_banner_url"
## [89] "profile_background_url" "profile_image_url"
## [91] "lat" "lng"
Y así fue, al final podemos ver que efectivamente se agregaron. Ahora filtremos los datos y quedemonos solo con los tweets que tienen coordenadas:
tweets_vacunacion_geo <- tweets_vacunacion %>%
filter(!is.na(lat), !is.na(lng))
Veamos cuantos quedaron:
nrow(tweets_vacunacion_geo)
## [1] 75
Solo quedaron 75 tweets de los 3100 originales, es decir que solo un 2,5% de los usuarios aceptaron que Twitter guarde información de sus ubicaciones. Lamentablemente esto ocurrirá la mayoría de veces y es bastante común que los usuarios no acepten que Twitter vea desde donde postean sus comentarios. De todos modos, aprovechemos esta info y hagamos un mapa para ver como se distribuye en el territorio:
bbox_general <- make_bbox(lon = tweets_vacunacion_geo$lng, lat = tweets_vacunacion_geo$lat)
mapa_general <- get_stamenmap(bbox_general,
maptype = "toner-lite",
zoom = 3)
ggmap(mapa_general)
ggmap(mapa_general) +
geom_point(data = tweets_vacunacion_geo, aes(x = lng, y = lat, size = followers_count, color = followers_count))+
scale_color_distiller(palette = "Spectral")+
theme_void()
Tal como habíamos visto cuando analizamos el orígen de los usuarios, podemos ver que los usuarios que twittearon sobre vacunación se ubican en diferentes países ya que al hacer la búsqueda no elegí tweets de ningun lugar en particular, simplemente puse un tema y descargué todo lo que había. Pero si quiero además de elegir la temática, limitar la ubicación espacial, también puedo hacerlo agregando un nuevo parámetro a mi búsqueda, y esto es lo que veremos en el próximo apartado.
Si estamos interesados en descargar tweets de un área específica debemos ajustar el parámetro geocode en la función search_tweets()
e indicar el centro y área de influencia donde quiero encontrar tweets. Probemos realizar la misma búsqueda pero solamente de tweets generados en AMBA, escribiendo las coordenadas del centro de CABA (Obelisco) y asignando un área de influencia de 20 millas (32km aprox):
#tweets_amba <- search_tweets(q = "VACUNACION OR VACUNAS",
# geocode = "-34.603722,-58.381592,20mi",
# include_rts = FALSE,
# n = 18000)
Al igual que antes, para poder replicar este manual con los mismos tweets, sugiero que carguen directamente la base:
tweets_amba <- readRDS(file = "tw_vacunacion_amba.rds")
¿Cuántos tweets de AMBA pude traerme?
dim(tweets_amba)
## [1] 17996 90
17996 tweets! Nada mal no? De todos modos, que se hayan descargado esta cantidad de tweets no quiere decir que Twitter me vaya a compartir las coordenadas de todos, probablemente solo unos pocos las tengan disponibles para ser mapeadas. Pero primero analicemos un poco el campo location donde no debería haber ningun sitio fuera de AMBA:
tweets_location_amba <- tweets_amba %>%
filter(location!="") %>%
group_by(location) %>%
summarise(cantidad=n()) %>%
arrange(desc(cantidad)) %>%
head(20)
tweets_location_amba
## # A tibble: 20 x 2
## location cantidad
## <chr> <int>
## 1 "Buenos Aires, Argentina" 7322
## 2 "Buenos Aires" 3131
## 3 "buenos aires" 314
## 4 "Quilmes, Argentina" 287
## 5 "Buenos Aires - Argentina" 281
## 6 "Tigre, Argentina" 224
## 7 "Lomas de Zamora, Argentina" 201
## 8 "Vicente López, Argentina" 201
## 9 "Buenos Aires, Argentina." 177
## 10 "San Isidro, Argentina" 159
## 11 "Ciudad Autónoma de Buenos Aire" 154
## 12 "Buenos Aires Argentina" 146
## 13 "Buenos Aires " 128
## 14 "San Fernando, Argentina" 110
## 15 "Berazategui, Argentina" 106
## 16 "Morón, Argentina" 96
## 17 "BUENOS AIRES" 88
## 18 "Argentina" 85
## 19 "Hurlingham, Argentina" 81
## 20 "Quilmes" 81
Tal como imaginabamos, en el campo location todos los usuarios declararon ser de AMBA, pero nuevamente nos encontramos con que difieren algunas formas de escribir. Veamos esto gráficamente:
ggplot(tweets_location_amba) +
geom_bar(aes(x = reorder(location, cantidad), weight=cantidad)) +
coord_flip() +
labs(title = "ORIGEN DE LOS USUARIOS",
x = "Ubicación",
y = "Cantidad")
Veamos cuantos tweets tienen coordenadas:
tweets_amba <- lat_lng(tweets_amba, coords = c("coords_coords", "bbox_coords", "geo_coords"))
Filtremos los valores nulos en las coordenadas:
tweets_amba_geo <- tweets_amba %>%
filter(!is.na(lat), !is.na(lng))
Y veamos cuantos tweets nos quedan:
nrow(tweets_amba_geo)
## [1] 1811
Tenemos 1811 datos con coordenadas geográficas. Es un número bastante interesante ya que representa un poco más del 10% de la muestra total. Veamoslos todos en un mapa:
bbox_amba <- make_bbox(lon = tweets_amba_geo$lng, lat = tweets_amba_geo$lat)
mapa_amba <- get_stamenmap(bbox_amba,
maptype = "terrain-lines",
zoom = 11)
ggmap(mapa_amba)
Tal como esperábamos, no hay ninguno fuera de AMBA. Agreguemos los tweets y asignemos color según cantidad de seguidores:
ggmap(mapa_amba) +
geom_point(data = tweets_amba_geo, aes(x = lng, y = lat, color = followers_count))+
scale_color_distiller(palette = "Spectral")+
theme_void()
Podrán ver que todos quedaron azules a pesar de haber rojo en la escala. Esto se debe a que los puntos se superponen y los que tienen mayor cantidad de seguidores quedaron por debajo. Arreglemos esto con un arrange()
:
ggmap(mapa_amba) +
geom_point(data = tweets_amba_geo %>% arrange(followers_count), aes(x = lng, y = lat, color = followers_count))+
scale_color_distiller(palette = "Spectral")+
theme_void()
Ahora si, vemos que el tweet generado por un usuario con más de 300000 seguidores se originó en el sur del AMBA. Agreguemos información en el tamaño de los puntos:
ggmap(mapa_amba) +
geom_point(data = tweets_amba_geo %>% arrange(followers_count), aes(x = lng, y = lat, color = followers_count, size = retweet_count))+
scale_color_distiller(palette = "Spectral")+
theme_void()
Podemos ver que no necesariamente el usuario más popular es el que tiene el tweet con más RT, de hecho, el tweet con aprox 500 RT lo tiene un usuario color celeste es decir con pocos seguidores. ¿Quién es el usuario y qué dice su tweet?
tweets_amba_geo %>%
filter(retweet_count==max(retweet_count)) %>%
select(screen_name, retweet_count, followers_count, location, text)
## # A tibble: 1 x 5
## screen_name retweet_count followers_count location text
## <chr> <int> <int> <chr> <chr>
## 1 CarlosMacia~ 542 15603 Ciudad Autón~ "Marcelo Figueiras, ~
Hasta acá solo vimos como mapear los tweets de forma estática, pero este tipo de datos también puede representarse en mapas interactivos, es decir mapas donde podemos hacer zoom, movernos, etc. En R obviamente hay un paquete específico para esto que se llama leaflet
(que ya lo instalamos y activamos al inicio de la clase), y tiene algunas similitudes con la lógica de ggplot.
Pero una posible debilidad de los mapas interactivos, al menos desde computadoras con procesadores “básicos/normales” es que pueden llegar a trabar o tildar la computadora si les cargamos demasiada información junta. Es por esto que tomaremos una muestra de un 10% de nuestros tweets georreferenciados para asegurarnos de poder hacer el mapa interactivo:
set.seed(123)
sample <- tweets_amba_geo %>%
sample_frac(0.1)
dim(sample)
## [1] 181 92
Hagamos el primer mapa interactivo:
leaflet(sample)
Como verán solo diciendole a R que quiero un leaflet()
con la base llamada sample no alcanza, tengo que sumar más información. Con addTiles()
agrego el mapa de fondo y con addMarkers()
se agregan los puntos:
leaflet(sample) %>%
addTiles() %>%
addMarkers()
## Assuming "lng" and "lat" are longitude and latitude, respectively
Y listo ya tenemos nuestro primer mapa interactivo! Fijense que pueden hacer zoom y moverlo. Pero aún podríamos agregarle más información no? Por ejemplo hacer que cuando toquemos el “pin” nos aparezca el texto del tweet. Esto se llama popup y se ajusta así:
leaflet(sample) %>%
addTiles() %>%
addMarkers(popup = ~text)
## Assuming "lng" and "lat" are longitude and latitude, respectively
Y esto no es todo! También podríamos cambiar el mapa de fondo por otro diferente, por ejemplo oscuro y modificar los íconos y ponerles el símbolo de Twitter:
leaflet(sample) %>%
addTiles() %>%
addProviderTiles(providers$CartoDB.DarkMatter) %>%
addAwesomeMarkers(popup = ~text, icon=awesomeIcons(icon = "twitter", library = "fa", iconColor = "black", markerColor = "blue"))
## Assuming "lng" and "lat" are longitude and latitude, respectively
O podríamos agregarle más información al popup:
leaflet(sample) %>%
addTiles() %>%
addProviderTiles(providers$CartoDB.DarkMatter) %>%
addAwesomeMarkers(popup = paste("User:", sample$screen_name, "<br>",
"Followers:", sample$followers_count, "<br>",
"Tweet:", sample$text),
icon=awesomeIcons(icon = "twitter", library = "fa", iconColor = "black", markerColor = "blue"))
## Assuming "lng" and "lat" are longitude and latitude, respectively
O podríamos nuevamente volver a la idea de colorear los puntos por cantidad de seguidores de la siguiente forma:
leaflet(sample %>% arrange(followers_count)) %>%
addTiles() %>%
addProviderTiles(providers$CartoDB.DarkMatter) %>%
addCircleMarkers(popup = paste("User:", sample$screen_name, "<br>",
"Followers:", sample$followers_count, "<br>",
"Tweet:", sample$text),
color = ~colorNumeric(palette = "viridis", domain = sample$followers_count)(followers_count)) %>%
addLegend(title = "seguidores", pal = colorNumeric(palette = "viridis", domain = sample$followers_count), values = ~followers_count)
## Assuming "lng" and "lat" are longitude and latitude, respectively
Y listo! Ahora les toca practicar a uds!
EJERCICIOS DE PRÁCTICA
Descargar tweets que se originen en los alrededores de la Ciudad con la que están trabajando.
Realizar al menos 2 de las siguientes consignas: