El objetivo de este trabajo es generar un análisis exploratorio sobre la actividad de los senadores nacionales de la República Argentina en la red social Twitter, registrar las variaciones que puedan tener entre ellos y controlarlo por variables accesorias como el género, la provincia por la que fueron electos y el interbloque al que pertenecen.
Para generar la base de datos con la que se trabajará fue necesario importar los tweets de los 62 senadores que tienen cuenta de Twitter mediante el paquete rtweet. Esta importación se realizó el 04/04/2021, por lo que la base de datos puede estar algo desactualizada.
#library(rtweet)
#Tweets_HCSN <- data.frame(matrix(nrow=0,ncol=0))
#Senadores <- c("anabelfsagasti","GugaLusto","estebanbullrich","marianorecalde","juliocobos","JorgeTaiana","gladys_gonzalez","mauricloss","JulioMartinezLR","alfredodeangeli","luisnaidenoff","SilviaEdePerez","CarlosMenem_LR","MatiasRodrigTDF","laurmachado","Weretilneck","EduardoCostaSC","claudiojpoggi","MarioFiad","OscarParrilli","SenadorLuenzo","espinolacamau","RomeroxSalta","nancysgonzalez","LupeTagliaferri","JAlperovichOk","sacnun","pilattivergara","PameVerasay","SchiavoniH","giacopposilvia","Juancmarino","dalmaciomera","adolfoRSquotes","Norma_Durango","AnaAlmironCtes","BeatrizMirkinOk","EdgardoKueider","guillermosnopek","RGBasualdo","juanmariopais","CaserioCarlos","SenadoraBlas","eugecatalfamo","mirabellarob","AnaMariaIanni","MaggieSolariQ","ReutemannC","PedroBraillardP","MariabTapia","LucilaCrexell","Oacastillo","Martinez_EF","VZimmermannOK","blancopabloda","ClaudiaLAZamora","Senadora_Olalla","DanielLoveraLP","sapag_silvia","AntonioRodas8","noragimenezok","JoseNederSDE")
#for (i in Senadores){
# Base <- get_timeline(i,n=3000)
#
# Tweets_HCSN <- rbind(Tweets_HCSN,Base)
#}
#
#save_as_csv(x = Tweets_HCSN,file_name = "Tweets_HCSN",fileEncoding = "UTF-8" )
Como generar esta función lleva mucho tiempo y se requiere estar logeado a una cuenta de Twitter, se accede a un CSV ya guardado.
#Se importa el CSV
Sen <- read_csv("Tweets_HCSN.csv")
#Se remueve los retweets y nos quedamos solo con el usuario y el texto del tweet
Sen <- Sen %>%
filter(is_retweet==FALSE) %>%
select(screen_name,text)%>%
rename(Senador=screen_name,Tweet=text)
head(Sen)
## # A tibble: 6 x 2
## Senador Tweet
## <chr> <chr>
## 1 anabelfsagas~ "El 10% del PBI tiene que ver con actividades vinculadas al tur~
## 2 anabelfsagas~ "Junto al ministro @MatiasLammens y la ministra @mariana_juri m~
## 3 anabelfsagas~ "@ernestoespeche @CeciJuriOk @LuliNieto8 @gustavocaleau @Marcel~
## 4 anabelfsagas~ "@EQuirogaGentile @lucasilardo @MarceloCostaMza @CiurcaC @Sergi~
## 5 anabelfsagas~ "Una de ellas, es el acueducto Monte Comán - La Horqueta, que p~
## 6 anabelfsagas~ "Nos reunimos con el intendente @emirfelixok y la EspecÃfica de~
Aquà generamos dos funciones que utilizaremos recurrentemente: - var_sen: agrega variables sustantivas sobre los senadores: interbloque, Género, provincia y región - limpiar_tokenizar: filtra de forma general los regex de tweets (copiado de https://rpubs.com/Joaquin_AR/334526)
#Creamos una función que agrega datos sustantivos de los senadores (Partido, Género, provincia y región)
var_sen <- function(data){
data %>%
mutate(Género=case_when(
Senador%in%c("anabelfsagasti","gladys_gonzalez","SilviaEdePerez","laurmachado",
"nancysgonzalez","LupeTagliaferri","sacnun","pilattivergara",
"PameVerasay","giacopposilvia","Norma_Durango","AnaAlmironCtes",
"BeatrizMirkinOk","SenadoraBlas","eugecatalfamo","AnaMariaIanni",
"MaggieSolariQ","MariabTapia","LucilaCrexell","ClaudiaLAZamora",
"Senadora_Olalla","sapag_silvia","noragimenezok")~"Mujer",
Senador%in%c("marianorecalde","JorgeTaiana","CarlosMenem_LR","MatiasRodrigTDF",
"OscarParrilli","SenadorLuenzo","JAlperovichOk",
"adolfoRSquotes","JoseNederSDE","CaserioCarlos","mirabellarob",
"espinolacamau","guillermosnopek","dalmaciomera","EdgardoKueider",
"juanmariopais","DanielLoveraLP","AntonioRodas8","GugaLusto",
"estebanbullrich","juliocobos","JulioMartinezLR","alfredodeangeli",
"luisnaidenoff","EduardoCostaSC","claudiojpoggi","SchiavoniH",
"Juancmarino","RGBasualdo","blancopabloda","PedroBraillardP",
"Oacastillo","VZimmermannOK","MarioFiad","Martinez_EF",
"mauricloss","Weretilneck","RomeroxSalta","ReutemannC")~"Hombre"),
Partido=case_when(
Senador%in%c("anabelfsagasti","marianorecalde","JorgeTaiana","CarlosMenem_LR",
"MatiasRodrigTDF","OscarParrilli","SenadorLuenzo",
"JAlperovichOk","sacnun","adolfoRSquotes","Norma_Durango",
"JoseNederSDE","BeatrizMirkinOk","AnaAlmironCtes","SenadoraBlas",
"CaserioCarlos","mirabellarob","ClaudiaLAZamora","eugecatalfamo",
"espinolacamau","noragimenezok","guillermosnopek",
"pilattivergara","nancysgonzalez","dalmaciomera",
"EdgardoKueider","juanmariopais","AnaMariaIanni",
"DanielLoveraLP","sapag_silvia","AntonioRodas8")~"FdT",
Senador%in%c("gladys_gonzalez","GugaLusto","estebanbullrich","juliocobos","estebanbullrich",
"JulioMartinezLR","alfredodeangeli","luisnaidenoff",
"SilviaEdePerez","EduardoCostaSC","claudiojpoggi",
"LupeTagliaferri","SchiavoniH","giacopposilvia","Juancmarino",
"RGBasualdo","blancopabloda","PedroBraillardP","Oacastillo",
"VZimmermannOK","PameVerasay","laurmachado","MarioFiad",
"MariabTapia","Senadora_Olalla","Martinez_EF")~"JxC",
Senador%in%c("mauricloss","Weretilneck","RomeroxSalta","MaggieSolariQ",
"ReutemannC","LucilaCrexell")~"otros"),
Provincia=case_when(
Senador%in%c("anabelfsagasti","juliocobos","PameVerasay")~"Mendoza",
Senador%in%c("marianorecalde","GugaLusto","LupeTagliaferri")~"CABA",
Senador%in%c("JorgeTaiana","gladys_gonzalez","estebanbullrich")~"Buenos Aires",
Senador%in%c("ReutemannC","sacnun","mirabellarob")~"Santa Fe",
Senador%in%c("alfredodeangeli","EdgardoKueider","Senadora_Olalla")~"Entre RÃos",
Senador%in%c("SenadoraBlas","Oacastillo","dalmaciomera")~"Catamarca",
Senador%in%c("pilattivergara","VZimmermannOK","AntonioRodas8")~"Chaco",
Senador%in%c("nancysgonzalez","SenadorLuenzo","juanmariopais")~"Chubut",
Senador%in%c("Martinez_EF","CaserioCarlos","laurmachado")~"Córdoba",
Senador%in%c("AnaAlmironCtes","PedroBraillardP","espinolacamau")~"Corrientes",
Senador%in%c("luisnaidenoff")~"Formosa",
Senador%in%c("MarioFiad","giacopposilvia","guillermosnopek")~"Jujuy",
Senador%in%c("Juancmarino","Norma_Durango","DanielLoveraLP")~"La Pampa",
Senador%in%c("CarlosMenem_LR","JulioMartinezLR")~"La Rioja",
Senador%in%c("mauricloss","MaggieSolariQ","SchiavoniH")~"Misiones",
Senador%in%c("LucilaCrexell","OscarParrilli","sapag_silvia")~"Neuquén",
Senador%in%c("Weretilneck")~"RÃo Negro",
Senador%in%c("noragimenezok","RomeroxSalta")~"Salta",
Senador%in%c("RGBasualdo")~"San Juan",
Senador%in%c("adolfoRSquotes","claudiojpoggi","eugecatalfamo")~"San Luis",
Senador%in%c("AnaMariaIanni","EduardoCostaSC","MariabTapia")~"Santa Cruz",
Senador%in%c("ClaudiaLAZamora","JoseNederSDE")~"Santiago del Estero",
Senador%in%c("blancopabloda","MatiasRodrigTDF")~"Tierra del Fuego",
Senador%in%c("SilviaEdePerez","JAlperovichOk","BeatrizMirkinOk")~"Tucumán")) %>%
mutate(Región=case_when(Provincia%in%c("Mendoza","San Juan","San Luis")~"Cuyo",
Provincia%in%c("Tierra del Fuego","Santa Cruz",
"RÃo Negro","Chubut","Neuquén")~"Patagonia",
Provincia%in%c("CABA","Buenos Aires","Córdoba","Santa Fe",
"Entre RÃos","La Pampa")~"Pampeana",
Provincia%in%c("Corrientes","Misiones","Formosa","Chaco")~"NEA",
Provincia%in%c("Jujuy","Salta","Tucumán","Catamarca",
"La Rioja","Santiago del Estero")~"NOA"))
}
limpiar_tokenizar <- function(texto){
# El orden de la limpieza no es arbitrario
# Se convierte todo el texto a minúsculas
nuevo_texto <- tolower(texto)
# Eliminación de páginas web (palabras que empiezan por "http." seguidas
# de cualquier cosa que no sea un espacio)
nuevo_texto <- str_replace_all(nuevo_texto,"http\\S*", "")
# Eliminación de signos de puntuación
nuevo_texto <- str_replace_all(nuevo_texto,"[[:punct:]]", " ")
# Eliminación de números
nuevo_texto <- str_replace_all(nuevo_texto,"[[:digit:]]", " ")
# Eliminación de espacios en blanco múltiples
nuevo_texto <- str_replace_all(nuevo_texto,"[\\s]+", " ")
# Tokenización por palabras individuales
nuevo_texto <- str_split(nuevo_texto, " ")[[1]]
# Eliminación de tokens con una longitud < 2
nuevo_texto <- keep(.x = nuevo_texto, .p = function(x){str_length(x) > 1})
return(nuevo_texto)
}
Ahora podemos comenzar a realizar algunos análisis exploratorios. Lo primero que vamos a medir es la cantidad de tweets producida por senador.
#,fig.width=10, fig.height=20
#Agrupamos la cantidad de tweets por usuario
Sen_tw <- Sen %>% group_by(Senador) %>% summarise("Número de tweets" = n())
Sen_tw <- var_sen(Sen_tw) %>% arrange(as.numeric(-`Número de tweets`))
head(Sen_tw)
## # A tibble: 6 x 6
## Senador `Número de tweets` Género Partido Provincia Región
## <chr> <int> <chr> <chr> <chr> <chr>
## 1 JulioMartinezLR 2767 Hombre JxC La Rioja NOA
## 2 RomeroxSalta 2693 Hombre otros Salta NOA
## 3 claudiojpoggi 2652 Hombre JxC San Luis Cuyo
## 4 SilviaEdePerez 2640 Mujer JxC Tucumán NOA
## 5 Juancmarino 2619 Hombre JxC La Pampa Pampeana
## 6 AnaMariaIanni 2614 Mujer FdT Santa Cruz Patagonia
Graficamos los resultados
g <- Sen_tw %>%arrange(-`Número de tweets`) %>%
ggplot(aes(x=reorder(Senador,`Número de tweets`),y=`Número de tweets`,
fill=Género))+geom_bar(stat = "identity")+
labs(x=NULL,y=NULL,title="Cantidad de tweets por senador y género")+
scale_fill_viridis_d()+
theme(panel.background = element_rect(fill = "white"),axis.text.y = element_text(size=7))+
coord_flip()
p <- Sen_tw %>%arrange(-`Número de tweets`) %>%
ggplot(aes(x=reorder(Senador,`Número de tweets`),y=`Número de tweets`,
fill=Partido))+geom_bar(stat = "identity")+
labs(x=NULL,y=NULL,title="Cantidad de tweets por senador e interbloque")+
scale_fill_viridis_d()+
theme(panel.background = element_rect(fill = "white"),axis.text.y = element_text(size=7))+
coord_flip()
r <- Sen_tw %>%arrange(-`Número de tweets`) %>%
ggplot(aes(x=reorder(Senador,`Número de tweets`),y=`Número de tweets`,
fill=Región))+geom_bar(stat = "identity")+
labs(x=NULL,y=NULL,title="Cantidad de tweets por senador y región")+
scale_fill_viridis_d()+
theme(panel.background = element_rect(fill = "white"),axis.text.y = element_text(size=7))+
coord_flip()
ggplotly(g)
ggplotly(p)
ggplotly(r)
Ahora vamos a intentar observar la cantidad de palabras distintas utilizadas en los tweets de los senadores.
Para eso tenemos que tokenizar todos los tweets y agruparlos por senador:
Sen_tok <- Sen %>% mutate(texto_tokenizado = map(.x = Tweet,.f = limpiar_tokenizar)) %>% select(-Tweet) %>% unnest() %>% rename(token = texto_tokenizado)
Sen_tok <- var_sen(Sen_tok)
Graficamos:
ggplotly(Sen_tok %>% distinct() %>%
ggplot(aes(x = Senador,fill=Partido)) + geom_bar()+coord_flip()+labs(x=NULL,y=NULL)+
scale_fill_viridis_d()+
labs(title="Cantidad de palabras utilizadas por tweet",
subtitle="Diferenciado por interbloque")+
theme(panel.background = element_rect(fill = "white"),axis.text.y = element_text(size=7)))
Ahora queremos revisar qué palabras se utilizaron con mayor frecuencia.
Para eso tendremos que: - Tokenizar los tweets - Filtrar las stop words - Distinguir entre partidos o género según conveniencia
Tomamos la base tokenizada y la filtramos por las stopwords y por algunos caracteres que no se pudieron filtrar con la fucnción de Regex:
custom_stop_words <- tm::stopwords("spanish") %>% as.data.frame() %>% rename(token=".")
filtro <- c("<u+","><u+","c>","fb>","c><u+fe","f>","><u+fe","f><u+","c><u+","d><u+")
Sen_tok_tidy <- Sen_tok %>% anti_join(custom_stop_words) %>% filter(!(token %in% filtro))
Sen_tok_tidy_x_sen <- Sen_tok_tidy %>% group_by(Senador, token) %>% count(token) %>% group_by(Senador) %>%top_n(10, n) %>% arrange(Senador, desc(n))
Sen_tok_tidy_x_sen <- var_sen(Sen_tok_tidy_x_sen)
head(Sen_tok_tidy_x_sen)
## # A tibble: 6 x 7
## # Groups: Senador [1]
## Senador token n Género Partido Provincia Región
## <chr> <chr> <int> <chr> <chr> <chr> <chr>
## 1 adolfoRSquotes san 266 Hombre FdT San Luis Cuyo
## 2 adolfoRSquotes luis 262 Hombre FdT San Luis Cuyo
## 3 adolfoRSquotes vamos 90 Hombre FdT San Luis Cuyo
## 4 adolfoRSquotes provincia 84 Hombre FdT San Luis Cuyo
## 5 adolfoRSquotes si 83 Hombre FdT San Luis Cuyo
## 6 adolfoRSquotes hacer 73 Hombre FdT San Luis Cuyo
Graficamos barras distinguiendo por género y por partido:
Sen_tok_tidy_x_sen %>% group_by(Género, token) %>% count(token) %>% group_by(Género) %>%
top_n(20, n) %>% arrange(Género, desc(n)) %>%
ggplot(aes(x = reorder(token,n), y = n, fill = Género)) +
geom_col() +
theme_bw() +
labs(y = "", x = "",title="Palabras utilizadas por género") +
theme(legend.position = "none") +
coord_flip()+
facet_wrap(~Género,scales = "free", drop = TRUE)+
scale_fill_manual(values = c("dark green","black"))+
theme_minimal()
Sen_tok_tidy_x_sen %>% group_by(Partido, token) %>% count(token) %>% group_by(Partido) %>%
top_n(10, n) %>% arrange(Partido, desc(n)) %>%
ggplot(aes(x = reorder(token,n), y = n, fill = Partido)) +
geom_col() +
theme_bw() +
labs(y = "", x = "",title="Palabras utilizadas por interbloque") +
theme(legend.position = "none") +
coord_flip()+
facet_wrap(~Partido,scales = "free", drop = TRUE)+
scale_fill_manual(values = c("blue","yellow","black"))+
theme_minimal()
Generamos un workcloud con todos los tweets. Se intentó realizar workcloud diferenciado por interbloque o género en el mismo gráfico, pero la función que habÃa encontrado online no tomaba palabras con tilde.
#Creamos un wordcloud
Sen_tok %>%
anti_join(custom_stop_words) %>%
filter(!(token %in% filtro)) %>%
count(token, sort=T) %>%
with(wordcloud(token, n, max.words = 100, color = brewer.pal(8, "Dark2")))
Ahora vamos a intentar observar qué palabras se usan más comunmente entre senadores de diferentes interbloques y de distinto género:
tweets_spread <- Sen_tok_tidy %>% group_by(Partido, token) %>% count(token) %>%
spread(key = Partido, value = n, fill = NA, drop = TRUE)
tweets_spread <- tweets_spread %>% select(token,FdT,JxC)
ggplot(tweets_spread, aes(FdT, JxC)) +
geom_jitter(alpha = 0.1, size = 2.5, width = 0.25, height = 0.25) +
geom_text(aes(label = token), check_overlap = TRUE, vjust = 1.5) +
scale_x_log10(labels = percent_format()) +
scale_y_log10(labels = percent_format()) +
geom_abline(color = "red") +
theme_bw()+ labs(title="Palabras usadas por senadores",subtitle="Frente de Todos y Juntos por el Cambio")+
theme(axis.text.x = element_blank(),
axis.text.y = element_blank())
tweets_spread_g <- Sen_tok_tidy %>% group_by(Género, token) %>% count(token) %>%
spread(key = Género, value = n, fill = NA, drop = TRUE)
ggplot(tweets_spread_g, aes(Mujer,Hombre)) +
geom_jitter(alpha = 0.1, size = 2.5, width = 0.25, height = 0.25) +
geom_text(aes(label = token), check_overlap = TRUE, vjust = 1.5) +
scale_x_log10(labels = percent_format()) +
scale_y_log10(labels = percent_format()) +
geom_abline(color = "red") +
labs(title="Palabras usadas por senadores",subtitle="Mujeres y Hombres")+
theme_bw()