Elaborar un dendograma para una búsqueda en twitter es un complemento a la nube de palabras. Mientras que en la nube de tags buscamos que palabras son más utilizadas y las jerarquizamos según el número de veces que se han citado, no buscamos relaciones semánticas entre ellas.
El análisis clúster a través de un dendograma de las conversaciones que se producen en una búsqueda en twitter nos permite ver las relaciones semánticas entre palabras, y cómo se relacionan entre ellas. Es decir, nos permite ver “que conversaciones” se están produciendo y no sólo que palabras son más utilizadas.
Perdemos la capacidad de la nube de tags de jerarquizar el peso de cada palabra, por lo tanto este análisis puede ser un buen complemento al de la nube de tags.
Si te interesa entender mejor cómo funciona un análisis clúster.
El resultado que tendremos de este script es el siguiente, una gráfica donde veremos un “dendograma” donde las palabras más utilizadas estarán presentes, las palabras cuanto más asociadas a una misma frase estén tendrán una relación jerárquica más cercana. Algunas, como en este caso, aparecen juntas en numerosas frases y están enlazadas al mismo nivel, pero otras tienen mucha mayor distancia (comparten menos frases comunes). Con esta estructura de relación semántica podemos agrupar las conversaciones y obtener “clústers” o grupos de conversaciones.
Un script que requiere más interpretación humana
La ejecución de este script tiene dos partes, una en la que introducimos los parámetros de búsqueda para que el script haga su trabajo, pero una segunda que nosotros tendremos que hacer el análisis de forma más intuitiva (pero aprovechando la capacidad de las librerías de R para hacer el análisis clúster). En esta parte interpretativa veremos el dendograma y decidiremos cuántos clústers queremos (entre 2 y 8), según el número de palabras que veamos y cómo intuitivamente veamos que podrían agruparse. Una vez el script elabora el número de clústers que creemos mejores, podremos etiquetarlos e identificarlos para crear una etiqueta que ayude a terceros a poder interpretar el dendograma.
dendograma.R
################################################ ### Cargamos las librerías necesarias ## twitter para descargar datos ## tm (Text Mining) ## RColorBrewer para tener librerías de colores ## wordcloud para nubes de palabras ############################################### library(twitteR) require(tm) library(wordcloud) library(RColorBrewer) ## ATENCIÓN USUARIOS DE WINDOWS: ## Esta parte es necesaria para los usuarios de Windows para ## superar problemas de permisos library(RCurl) options(RCurlOptions = list(cainfo = system.file("CurlSSL", "cacert.pem", package = "RCurl"))) u = "https://raw.github.com/tonybreyal/Blog-Reference-Functions/master/R/bingSearchXScraper/bingSearchXScraper." x = getURL(u, cainfo = system.file("CurlSSL", "cacert.pem", package = "RCurl")) ## Autentificación con twitter, tienes que tener tu propio fichero .RData acreditado load("rcredenciales.RData") ## El tener tu propio .RData autentificado es una parte compleja registerTwitterOAuth(tw) ##################### Aclaración para conseguir tu .RData ###################### ## Una explicación de cómo obtenerlo: ## ## 1.- Necesitas darte de alta como desarrollador ## en dev.twitter.com ## 2.- Da de alta una app y consigue tu consumer key ## y tu secret ke y. ## 3.- Sigue los primeros pasos hasta conseguir el .RData: ## http://aaronccrowley.wordpress.com/2013/05/27/extracting-data-from-twitter-with-r/ ## ## Alerta: si eres usuario de windows en el script citado ## tendrás que incluir las líneas 42 a 50 del actual Script al inicio del Script ## indicado en la web #################################################### ############## Definición de variables ########################### ## k es un número ## k define el número de clústers ## k es preguntado una vez elaborado el dendograma ## terminobusqueda = String ## Es el nombre del usuario del que quiero buscar su nube de tags terminobusqueda = readline("¿Cuál es el término de la búsqueda? ") # pequeño código para evitar dejar vacío el término de búsqueda while (terminobusqueda =="") terminobusqueda = readline("Por favor, define un término de búsqueda ") ## TweetNumber = Number ## Es el número de twitts en los que quiero ahondar TweetNumber = readline("¿Cuantos tweets quieres analizar? ") TweetNumber = as.numeric(unlist(strsplit(TweetNumber, ","))) ## geografico = string (number(latitud), number(longitud), number+km(radio geogr?fico)) o NULL ## Es una variable que permite acotar las búsquedas a twitts geolocalizados print ("Ejemplos de datos geográficos, Barcelona, 150km a la redonda:41.378476,2.1701334,150km") geografico = readline("Ámbito geográfico, dejar vacio si no se quiere geolocalizar ") if (geografico=="") geografico=NULL ## palabrasstop -> string ## String de palabras que no queremos que aparezcan en el dendograma palabrasstop = readline("Define las palabras que no quieres que aparezcan (separadas por espacios y en minúsculas) ") palabrasstop = unlist(strsplit(palabrasstop, split=" ")) ############################################ ## Ejecutamos la descarga de datos de twitter ############################################ mach_tweets = searchTwitter(terminobusqueda, n=TweetNumber, geocode=geografico) mach_text = sapply(mach_tweets, function(x) x$getText()) ########## Establezco el sistema local del idioma (solo para usuarios Windows) Sys.setlocale("LC_CTYPE", "spanish") ## Función implícita no definida ## Transforma una Lista() en otra Lista() ## Objetivo: Sustituye los carácteres mal descargados por ## carácteres latinos que los scripts puedan leer sin problemas mach_text = tolower(mach_text) mach_text = gsub("ã¡", "a", mach_text) mach_text = gsub("ã©", "e", mach_text) mach_text = gsub("ã³", "o", mach_text) mach_text = gsub("ãº", "u", mach_text) mach_text = gsub("ã±", "ñ", mach_text) mach_text = gsub("ã¨", "e", mach_text) mach_text = gsub("ã²", "o", mach_text) mach_text = gsub("ã", "i", mach_text) ## Eliminamos los términos de b?squeda ## Transformamos una lista en otra lista mach_text = gsub(terminobusqueda, "", mach_text) ## Se define la función clean.text ## Transforma una Lista() en otra Lista() ## Objetivo: Filtra palabras (evita URL, @usuarios, etc...) ## clean.text = function(x) { # tolower x = tolower(x) # remove rt x = gsub("rt", "", x) # remove at x = gsub("@\\w+", "", x) # remove punctuation x = gsub("[[:punct:]]", "", x) # remove numbers x = gsub("[[:digit:]]", "", x) # remove links http x = gsub("http\\w+", "", x) # remove tabs x = gsub("[ |\t]{2,}", "", x) # remove blank spaces at the beginning x = gsub("^ ", "", x) # remove blank spaces at the end x = gsub(" $", "", x) return(x) } ### Hacemos la limpieza de texto mach_text = clean.text(mach_text) # Construimos un corpus mydata.corpus = Corpus(VectorSource(mach_text)) # volvemos a asegurar que las palabras estarán en minúsculas mydata.corpus = tm_map(mydata.corpus, tolower) # eliminamos la puntuación mydata.corpus = tm_map(mydata.corpus, removePunctuation) # elimina palabras comunes (del castellano y del catalán) my_stopwords = c(stopwords('spanish'),stopwords('catalan'), palabrasstop) mydata.corpus = tm_map(mydata.corpus, removeWords, my_stopwords) # Transformamos elcurpus en una matriz mydata.dtm = TermDocumentMatrix(mydata.corpus) # inspeccionamos la matriz mydata.dtm # inspeccionamos las palabras más relevantes findFreqTerms(mydata.dtm, lowfreq=30) # Eliminamos los sparse terms para simplificar los clusters # Si aumentamos el valor de sparse saldrán más palabras. # Con la actual configuración tendremos entre 10 y 30 palabras # Que es ideal para poder trabajar. mydata.dtm2 = removeSparseTerms(mydata.dtm, sparse=0.95) # Transformamos la matriz en un data frame mydata.df = as.data.frame(inspect(mydata.dtm2)) # hacemos algunas comprobaciones sobre el dataframe nrow(mydata.df) ncol(mydata.df) mydata.df.scale = scale(mydata.df) d = dist(mydata.df.scale, method = "euclidean") # definimos la distancia fit = hclust(d, method="ward") # definimos el método para hacer clusters ############################ ## Dibujamos el dendograma ############################ ## Parte 1 # Generamos el dendograma plot(fit, main="") # Ponemos un título al dendograma titulo = c("Dendograma en twitter de ", terminobusqueda) title(titulo) ## Parte 2 ## Dibujamos los clusters k = readline("¿Cuántos clústers quieres dibujar? ") k = as.numeric(unlist(strsplit(k, ","))) rect.hclust(fit, k, border=rainbow(k)) ### Parte 3, interpretación del dendograma ## Pedimos al usuario que identifique ## cada cluster y le de una definición para ## poder escribir la leyenda cluster1 = NULL cluster2 = NULL cluster3 = NULL cluster4 = NULL cluster5 = NULL cluster6 = NULL cluster7 = NULL cluster8 = NULL cluster1 = readline("¿Cómo defines el primer clúster? ") cluster2 = readline("¿Cómo defines el 2o clúster? ") if (k>2) cluster3 = readline("¿Cómo defines el 3er clúster? ") if (k>3) cluster4 = readline("¿Cómo defines el 4o clúster? ") if (k>4) cluster5 = readline("¿Cómo defines el 5o clúster? ") if (k>5) cluster6 = readline("¿Cómo defines el 6o clúster? ") if (k>6) cluster7 = readline("¿Cómo defines el 7o clúster? ") if (k>7) cluster8 = readline("¿Cómo defines el 8o clúster? ") ## Dibujamos la leyenda segun los criterios del ## usuario. labels.clusters = c(cluster1, cluster2, cluster3, cluster4, cluster5, cluster6, cluster7, cluster8) legend("topright", legend = labels.clusters, fill = rainbow(k), title = "Clusters", box.col = "black", bg="transparent")