# install.packages("rtweet")
library(rtweet)
library(tidyverse)
library(tm)
library(wordcloud2)
rtweet
rt <- search_tweets(q = "metrovias OR bondi OR Subte OR autopista OR transporte público",type = "mixed", n = 18000, include_rts = FALSE,
lang='es')
saveRDS(rt,'../fuentes/rt.RDS')
rt <- read_rds('../fuentes/rt.RDS')
rt %>%
sample_n(10)
range(rt$created_at)
[1] "2019-09-13 03:04:47 UTC" "2019-09-21 18:24:56 UTC"
Nos da los tweets de los últimos nueve días, o el máximo que indicamos más reciente
rt %>%
ts_plot("3 hours") +
ggplot2::theme_minimal() +
ggplot2::theme(plot.title = ggplot2::element_text(face = "bold")) +
ggplot2::labs(
x = NULL, y = NULL,
title = "Frecuencia de los tweets relacionados al tránsito",
subtitle = "Agregado a intervalos de tres horas")
texto <- rt$text
texto[1:10]
[1] "▶ Dos sujetos robaron a usuarios de un vehículo de transporte público https://t.co/3c0fSjKrWF https://t.co/uGYN8CyLuZ"
[2] "Detienen a dos menores por asalto a transporte público https://t.co/R2VNKPLV0v https://t.co/MOVow5LUiE"
[3] "Detienen a dos menores por asalto a transporte público\n\nhttps://t.co/6Ff1iewafX https://t.co/eRfyw8RLZy"
[4] "Hombres armados incendian transporte público en #Acapulco https://t.co/WPPQqGckq9 https://t.co/LRzjM0mvPO"
[5] "Hombres armados incendian transporte público en #Acapulco https://t.co/FbmZNWJPKN https://t.co/VSNemKS0S5"
[6] "Según la Veeduría Distrital, la capital necesita con urgencia reducir las emisiones de CO2, producidos principalmente por el transporte público y los vehículos de carga pesada. https://t.co/oSJYsyMRu5"
[7] "El #CMin aprueba un RD para mejorar la #accesibilidad al transporte de las personas con #discapacidad.\n\n♿️Acceso de las sillas de ruedas eléctricas y escúteres a los medios de transporte.\n🐕Afectados por epilepsia y diabetes podrán viajar en transporte público con su perro. https://t.co/MW5BTsZzgB"
[8] "Ósea el asunto no es solo así por así, hay que tener en cuenta otras medidas como el Transporte, la eficiencia del transporte público etc. \nDejen de andar pidiendo desniveles como dulces porque aparentemente ni en Peru esa es la solución. \nCierro hilo."
[9] "@cronicaglobal TODOS queremos un transporte Público sostenible, pero lo queremos eficiente...Esperas mas de 6 minutos en hora punta no es eficiencia..."
[10] "Me caga cuando alguna persona se le queda viendo a mi cartera cuando la saco para pagar el transporte público. \nQue esperan ver? Un chingo de billetes? …......\nNo ven que estoy igual de jodido que ellos y por eso voy en la combi también."
Este texto es necesario limpiarlo para que sea más fácil de utilizar.
tm
myCorpus = Corpus(VectorSource(texto))
tm_map
podemos iterar sobre el corpus aplicando una transformación sobre cada documento (se acuerdan de la librería PURRR
?)En este caso, para la limpieza utilizaremos las siguientes transformaciones.
tm
tenemos que usar también content_transformer
)myCorpus = tm_map(myCorpus, content_transformer(tolower))
myCorpus = tm_map(myCorpus, removePunctuation)
myCorpus = tm_map(myCorpus, removeNumbers)
myCorpus = tm_map(myCorpus, removeWords, stopwords(kind = "es"))
También deberíamos sacar las palabras que utilizamos para descargar la información.
# metrovias OR bondi OR Subte OR autopista OR transporte público
myCorpus = tm_map(myCorpus, removeWords, c('metrovias', 'bondi','subte','autopista','transporte', 'público' ))
transformation drops documents
inspect(myCorpus[1:10])
<<SimpleCorpus>>
Metadata: corpus specific: 1, document level (indexed): 0
Content: documents: 10
[1] ▶ dos sujetos robaron usuarios vehículo httpstcocfsjkrwf httpstcougyncyluz
[2] detienen dos menores asalto httpstcorvnkplvv httpstcomovowluie
[3] detienen dos menores asalto \n\nhttpstcoffiewafx httpstcoerfywrlzy
[4] hombres armados incendian acapulco httpstcowppqqgckq httpstcolrzjmmvpo
[5] hombres armados incendian acapulco httpstcofbmznwjpkn httpstcovsnemkss
[6] según veeduría distrital capital necesita urgencia reducir emisiones co producidos principalmente vehículos carga pesada httpstcoosjysymru
[7] cmin aprueba rd mejorar accesibilidad personas discapacidad\n\n♿️acceso sillas ruedas eléctricas escúteres medios \n🐕afectados epilepsia diabetes podrán viajar perro httpstcomwbtszzgb
[8] ósea asunto solo así así tener cuenta medidas eficiencia etc \ndejen andar pidiendo desniveles dulces aparentemente peru solución \ncierro hilo
[9] cronicaglobal queremos sostenible queremos eficienteesperas mas minutos hora punta eficiencia
[10] caga alguna persona queda viendo cartera saco pagar \n esperan ver chingo billetes …\n ven igual jodido voy combi
podemos ver que nos quedaron unos que son la forma de representar el “enter”. Lo mejor sería eliminarlos.
También queremos sacar los links. Para eso vamos a usar expresiones regulares para definir el patron que tiene un link, y luego crearemos una función que los elimine.
Para que sea más sencilla la construcción de la expresión regular, usamos la librería RVerbalExpressions
# devtools::install_github("VerbalExpressions/RVerbalExpressions")
library(RVerbalExpressions)
expresion <- rx() %>%
rx_find('http') %>%
rx_maybe('s') %>%
# rx_maybe('://') %>% #como ya lo pasamos por los otros filtros, ya no hay puntuacion
rx_anything_but(value = ' ')
expresion
[1] "(http)(s)?([^ ]*)"
Probamos la expresion con un ejemplo
txt <- "detienen dos menores asalto transporte público\n\nhttpstcoffiewafx httpstcoerfywrlzy"
str_remove_all(txt, pattern = expresion)
[1] "detienen dos menores asalto transporte público\n\n "
Lo pasamos por el corpus
myCorpus = tm_map(myCorpus, content_transformer(function(x) str_remove_all(x, pattern = expresion)))
transformation drops documents
myCorpus = tm_map(myCorpus, content_transformer(function(x) str_remove_all(x, pattern = '\n')))
transformation drops documents
inspect(myCorpus[1:10])
<<SimpleCorpus>>
Metadata: corpus specific: 1, document level (indexed): 0
Content: documents: 10
[1] ▶ dos sujetos robaron usuarios vehículo
[2] detienen dos menores asalto
[3] detienen dos menores asalto
[4] hombres armados incendian acapulco
[5] hombres armados incendian acapulco
[6] según veeduría distrital capital necesita urgencia reducir emisiones co producidos principalmente vehículos carga pesada
[7] cmin aprueba rd mejorar accesibilidad personas discapacidad♿️acceso sillas ruedas eléctricas escúteres medios 🐕afectados epilepsia diabetes podrán viajar perro
[8] ósea asunto solo así así tener cuenta medidas eficiencia etc dejen andar pidiendo desniveles dulces aparentemente peru solución cierro hilo
[9] cronicaglobal queremos sostenible queremos eficienteesperas mas minutos hora punta eficiencia
[10] caga alguna persona queda viendo cartera saco pagar esperan ver chingo billetes … ven igual jodido voy combi
Creamos una matriz de Término-documento
myDTM = DocumentTermMatrix(myCorpus, control = list(minWordLength = 1))
inspect(myDTM)
<<DocumentTermMatrix (documents: 17697, terms: 43484)>>
Non-/sparse entries: 227647/769308701
Sparsity : 100%
Maximal term length: 137
Weighting : term frequency (tf)
Sample :
Terms
Docs así ciudad gente metro movilidad publico ser servicio sistema uso
10446 0 1 0 0 0 1 0 0 0 0
11678 0 0 0 0 0 0 0 0 0 0
11689 0 0 0 0 0 0 0 0 0 0
12916 0 0 0 0 0 0 0 0 0 0
13169 0 0 1 0 0 0 0 0 0 0
13736 0 0 0 1 0 0 0 0 0 0
16210 0 0 0 0 0 1 0 0 0 0
2359 0 0 0 0 0 0 0 0 0 0
3539 0 0 0 0 0 0 0 0 0 0
5963 0 0 0 0 2 0 0 0 0 0
palabras_frecuentes <- findMostFreqTerms(myDTM,n = 25, INDEX = rep(1,nDocs(myDTM)))[[1]]
palabras_frecuentes
publico gente ciudad metro servicio ser movilidad así sistema uso
1425 1081 1026 934 890 737 692 583 572 572
hoy mejor día solo hacer personas mejorar menos hace usar
560 557 553 533 532 512 498 495 491 485
bien puede vez calidad tener
461 447 446 443 441
palabras_frecuentes <- tibble(word = names(palabras_frecuentes), freq =palabras_frecuentes)
wordcloud2(palabras_frecuentes, shuffle = FALSE)
necesito eliminar los documentos vacíos (que luego de la limpieza quedaron sin ningúna palabra)
ui = unique(myDTM$i)
dtm = myDTM[ui,]
dim(myDTM)
[1] 17697 43484
dim(dtm)
[1] 17677 43484
lda_fit <- LDA(dtm, k = 10,method = "Gibbs", control = list(delta=0.6,seed = 1234))
lda_fit
saveRDS(lda_fit,'../resultados/lda_fit.rds')
Terms <- terms(lda_fit, 10)
Terms
Topic 1 Topic 2 Topic 3 Topic 4 Topic 5 Topic 6 Topic 7 Topic 8
[1,] "mejorar" "movilidad" "servicio" "ciudad" "día" "gente" "pasajeros" "publico"
[2,] "hace" "uso" "ser" "pasaje" "cada" "metro" "vía" "seguridad"
[3,] "puede" "coche" "madrid" "bogotá" "hoy" "enciudad" "unidades" "casa"
[4,] "medio" "vehículos" "mejor" "sabe" "vez" "luisdejesus" "usuarios" "auto"
[5,] "centro" "semana" "personas" "claudialopez" "hora" "viajar" "aumento" "atención"
[6,] "años" "bici" "debe" "parís" "trabajo" "ahora" "tarifa" "llegar"
[7,] "tránsito" "bicicleta" "buen" "tan" "menos" "caminar" "sep" "espacio"
[8,] "algún" "ciudad" "vas" "huelga" "bien" "país" "unidad" "luego"
[9,] "utilizar" "privado" "debería" "reforma" "horas" "crisis" "falta" "seguro"
[10,] "evitar" "millones" "defensa" "precio" "voy" "caracas" "dos" "cuenta"
Topic 9 Topic 10
[1,] "sistema" "usar"
[2,] "calidad" "solo"
[3,] "hacer" "mejor"
[4,] "problema" "van"
[5,] "gobierno" "mal"
[6,] "tener" "así"
[7,] "parte" "buses"
[8,] "claudiashein" "vida"
[9,] "cdmx" "menos"
[10,] "autos" "bien"
topicmodels_json_ldavis <- function(fitted, dtm){
svd_tsne <- function(x) tsne(svd(x)$u)
# Find required quantities
phi <- as.matrix(posterior(fitted)$terms)
theta <- as.matrix(posterior(fitted)$topics)
vocab <- colnames(phi)
term_freq <- slam::col_sums(dtm)
# Convert to json
json_lda <- LDAvis::createJSON(phi = phi, theta = theta,
vocab = vocab,
mds.method = svd_tsne,
plot.opts = list(xlab="tsne", ylab=""),
doc.length = as.vector(table(dtm$i)),
term.frequency = term_freq)
return(json_lda)
}
json_res <- topicmodels_json_ldavis(lda_fit, dtm)
sigma summary: Min. : 33554432 |1st Qu. : 33554432 |Median : 33554432 |Mean : 33554432 |3rd Qu. : 33554432 |Max. : 33554432 |
Epoch: Iteration #100 error is: 12.8836114015732
Epoch: Iteration #200 error is: 0.545783211585834
Epoch: Iteration #300 error is: 0.316667061007205
Epoch: Iteration #400 error is: 0.283525281163514
Epoch: Iteration #500 error is: 0.2697498397927
Epoch: Iteration #600 error is: 0.26385292509649
Epoch: Iteration #700 error is: 0.257183697971322
Epoch: Iteration #800 error is: 0.253367621152415
Epoch: Iteration #900 error is: 0.252756387349672
Epoch: Iteration #1000 error is: 0.252670353596606
serVis(json_res)
Loading required namespace: servr
To stop the server, run servr::daemon_stop(1) or restart your R session
Serving the directory /tmp/RtmpxDpSCC/file263b7d5d0dfb at http://127.0.0.1:4321