En este ejercicio vamos a intentar de analizar los comentarios en la red social Twitter de una empresa u organización en particular para conocer como son las opiniones que recibe que esten vinculadas al nombre de la empresa.
Para poder realizar este ** “Análisis de sentimiento” ** lo que vamos a hacer es utilizar la API de Twitter dándonos de alta como desarrollador y crear una aplicación para a través de la cual acceder a los datos de Twitter de una cuenta determinada. A partir de ahí haremos una limpieza de los datos para obtener los elementos con los que trabajar y realizar un analisis de datos.
Debemos tener en cuenta que en algunos casos el análisis de sentimiento en redes sociales se puede complicar según el tema, puesto para una situación concreta un comentario puede ser clasificado como negativo al no tener en cuenta el contexto. Así, por ejemplo, en una situación de guerra que haya comentarios negativos es entendible, y si esos comentarios se mezclan con otros en la cual no debería haber comentarios negativos se produce una mezcla inconcluyente. Más aún, es común que en muchos idiomas, entre ellos el español, palabras que en un principio son negativas, pueden ser usadas en tono amistoso.
Por lo tanto, para obtener resultados realistas y con un algoritmo que funcione bien se debe tener el contexto y elegir bien la muestra.
Veamos los pasos que hemos seguido para realizar este análisis.
Abrir una cuenta de desarrollador Antes de empezar hay que darse de alta en Twitter como desarrollador utilizando la cuenta personal de la red social y registrar un App en el API: *https://apps.twitter.com/.*
En este caso hemos denominado la app de twitter como “Twitter Sentiment Analysis. UNED”. Una vez creada la app generamos una serie de tokens de acceso (Access token y * Access token secret ) y claves de la API (api_key* y API secret key). Estos son las claves y tokens generados:
api_key <- " rn6qOI9nUcnuA11r7sdQEcRGu "
api_secret <- " alAtSqZK1uWOs7O89YnwkqMRVBdIYPyaOl3gry2rXFkU1LnkpI "
access_token <- " 920582805981188097-q5R0cMpWxFK3cQoDN7vGyYj7sRvxLO8 "
access_token_secret <- " fu3q0vy8NiZlF2pwn6y5CD8SCwcEZmiRIPBRTjprQFGeM"
twitter_app <- " Twitter Sentiment Analysis. UNED"
Estas claves las podemos regenerar siempre que queramos.
Una vez creada la cuenta de desarrollador y generadas las claves y tokens podemos instalar algunos paquetes necesarios para realizar el análisis de sentimiento.
Instalamos algunos paquetes
if(!is.element("Rstem", installed.packages()[, 1]))
install.packages("Rstem", repos = 'http://cran.us.r-project.org')
install.packages("sentiment", repos = "http://www.omegahat.org/R", type = "source")
if(!is.element("sentiment", installed.packages()[, 1]))
install.packages("sentiment", repos = 'http://cran.us.r-project.org')
if(!is.element("devtools", installed.packages()[, 1]))
install.packages("devtools", repos = 'http://cran.us.r-project.org')
require(devtools)
if(!is.element("twitteR", installed.packages()[, 1]))
install.packages("twitteR", repos = 'http://cran.us.r-project.org')
install.packages("Rstem", repos = "http://www.omegahat.org/R", type = "source")
install_url("http://cran.r-project.org/src/contrib/Archive/sentiment/sentiment_0.2.tar.gz")
require(sentiment)
ls("package:sentiment")
if(!is.element("tm", installed.packages()[, 1]))
install.packages("tm", repos = 'http://cran.us.r-project.org')
if(!is.element("httr", installed.packages()[, 1]))
install.packages("httr", repos = 'http://cran.us.r-project.org')
if(!is.element("rjson", installed.packages()[, 1]))
install.packages("rjson", repos = 'http://cran.us.r-project.org')
if(!is.element("bit64", installed.packages()[, 1]))
install.packages("bit64", repos = 'http://cran.us.r-project.org')
if(!is.element("RCurl", installed.packages()[, 1]))
install.packages("RCurl", repos = 'http://cran.us.r-project.org')
install.packages("wordcloud")
Cargamos las librerías
# library(twitteR)
if(!is.element("rtweet", installed.packages()[,1]))
install.packages("rtweet", repos = 'http://cran.us.r-project.org')
library(rtweet)
library(wordcloud)
## Loading required package: RColorBrewer
library(RColorBrewer)
library(plyr)
library(ggplot2)
library(sentiment)
## Loading required package: tm
## Loading required package: NLP
##
## Attaching package: 'NLP'
## The following object is masked from 'package:ggplot2':
##
## annotate
## Loading required package: Rstem
Una vez cargadas las librerias, accedemos a Twitter a través de los datos del token.
api_key <- "lhoFGi7WwTCNweSwjLAf0pcsO"
api_secret <- "HX5YP7MaRb0pri3G73tbIIqvv8qbUGiptsY4fsL9bCN6YjN9zv"
access_token <- "920582805981188097-kydfkJ915usop34k1VQd9uMBVKTxnaL"
access_token_secret <- "73LOfzcjfIPlUUNoDVOVXYt5uEpBPaiM16EnSk9HD7pUO"
twitter_app <- " Twitter Sentiment Analysis. UNED"
# Accedemos a Twitter a través de los datos del token
create_token(
app = twitter_app,
consumer_key = api_key,
consumer_secret = api_secret,
access_token = access_token,
access_secret = access_token_secret)
## <Token>
## <oauth_endpoint>
## request: https://api.twitter.com/oauth/request_token
## authorize: https://api.twitter.com/oauth/authenticate
## access: https://api.twitter.com/oauth/access_token
## <oauth_app> Twitter Sentiment Analysis. UNED
## key: lhoFGi7WwTCNweSwjLAf0pcsO
## secret: <hidden>
## <credentials> oauth_token, oauth_token_secret
## ---
Antes de cargar los datos con los que queremos hacer el análisis de sentimiento podríamos ejecutar algunas funciones que nos ofrece la librería rtweet como langs para ver el lenguaje aceptado por Twittter o emojis
A partir de ahora, una vez conectados con el API de Twitter, podemos cargar los datos con los que queremos trabajar.
Una vez que se completa la autorización, podemos ejecutar una búsqueda. Para este ejemplo, vamos a realizar una búsqueda de los tweets que mencionan una marca conocida: Uber España @Uber.
Vamos a restringir el resultado a una muestra total de 10.000 tweets escritos en inglés (lang = “en”). Si queremos que no se incluyan los Rtweets debemos incluir la siguiente función include_rts = FALSE. También es posible dar un rango de fechas y restricciones geográficas.
# Busqueda de la palabra Uber en español con geocode situado en Madrid y un radio de 600km.
uber_tweets <- search_tweets("Uber", n = 10000, include_rts = FALSE, lang="es", geocode = "40.42028,-3.70577,600km")
## Searching for tweets...
## Finished collecting tweets!
Sacamos el texto de los tweets.
# Sacamos el texto y lo definimos con la siguiente variable
uber_txt <- uber_tweets$text
# Otra forma de coger el texto
# some_txt = sapply(some_tweets, function(x) x$getText())
# Mostramos los 10 primeros
head(uber_txt, 10)
## [1] "Y luego algunos sin materia gris andan defendiendo a #Uber y #Cabify. Pues aquí tenéis un claro ejemplo de lo que pasaría si el #Taxi dejara de prestar servicio. Ceporros, que os merecéis toda la mierda que tenéis, que no es poca. Españistán <f0><U+009F><U+0087><U+00AA><f0><U+009F><U+0087><U+00B8> https://t.co/s896P8ksDI"
## [2] "@boye_g @loputosatir Esto no ha hecho más que empezar <f0><U+009F><U+0091><U+008C>https://t.co/ILohDHTN1P"
## [3] "Yo si fuese un #violador, sin lugar a dudas me metía a trabajar en un #Uber #Cabify. Allí no me exigen nada y tengo muchas victimas donde elegir #cabifymola #deleteUber #QuienAvisaNoEsTraidor"
## [4] "@PesetoLoco @firstdates_tv @Uber @cabify_espana Hoy en fisrt dates, precariedad en estado puro! Quien pagará la cena? <f0><U+009F><U+00A7><U+0090>"
## [5] "Nosotros cumpliendo las leyes día si y día también, y los piratas de #Uber y #cabify haciendo lo que les da la gana. Hace tiempo que ya estamos cansados de esta situación. Aeropuerto del Prat @aena, zona de salidas. Los @mossos ni están ni se les espera... Can picha. https://t.co/KYB263eTrh"
## [6] "Hola @cabify_espana tengo entendido que si soy un violador y un pedófilo ex presidiario, puedo trabajar con vosotros, que no hay ningún problema. Como lo hago? Tengo que hacer solo un curso de 1h verdad? #Cabify #Uber"
## [7] "@nunurob @Uber_ES A ver si tienes suerte y te lo devuelven Nuria, lo que hacen es una práctica habitual de estas empresas. Hay miles de denuncias en @LeaksUberCabify. Confía en el #taxi de siempre, legal y honrado y también tienen apps muy buenas. Saludos!"
## [8] "@oscar_herranz @airbnb_es @Uber @cabify_espana La economía global o el esclavismo del siglo XXI? <f0><U+009F><U+00A4><U+00A3> por cierto, ya veremos si se bloquean o no, este otoño o se bloquean esas apps o se bloquean las ciudades. A ver quien la tiene más grande <f0><U+009F><U+0098><U+0089>"
## [9] "@TAXIDRI87187936 @manowl @Uber_ES Si es amigo de nuestro enemigo, entonces no le ayudes. Que encima no da ni las gracias <f0><U+009F><U+0098><U+00AC> que se apañen las mierdas entre ellos <f0><U+009F><U+0098><U+008A>"
## [10] "Otra vez vuelve a pasar, un conductor de aplicación viola y mata a una chica joven #Uber #Cabify #Didi #VTC #Machismo https://t.co/A0SE53PGX8"
ETL en RRSS
Ahora que tenemos los mensajes de Twitter, debemos limpiarlos antes de hacer cualquier análisis. Esto implica eliminar cierto contenido, como la puntuación, que no tiene contenido emocional y eliminar cualquier contenido que cause errores.
En general al trabajar con Redes Sociales se suelen hacer una serie de pasos para limpiar los datos, los cuales generalmente son: • Minúsculas. • Quitar nombres (@) • Quitar puntuación • Stopwords (palabras repetitivas). • Eliminación de números si fuese necesario.*
Quitamos los retweets
uber_txt <- gsub("(RT|via)((?:\\b\\W*@\\w+)+)", "", uber_txt)
# Veamos los 10 primeros tweets
head(uber_txt, 10)
## [1] "Y luego algunos sin materia gris andan defendiendo a #Uber y #Cabify. Pues aquí tenéis un claro ejemplo de lo que pasaría si el #Taxi dejara de prestar servicio. Ceporros, que os merecéis toda la mierda que tenéis, que no es poca. Españistán <f0><U+009F><U+0087><U+00AA><f0><U+009F><U+0087><U+00B8> https://t.co/s896P8ksDI"
## [2] "@boye_g @loputosatir Esto no ha hecho más que empezar <f0><U+009F><U+0091><U+008C>https://t.co/ILohDHTN1P"
## [3] "Yo si fuese un #violador, sin lugar a dudas me metía a trabajar en un #Uber #Cabify. Allí no me exigen nada y tengo muchas victimas donde elegir #cabifymola #deleteUber #QuienAvisaNoEsTraidor"
## [4] "@PesetoLoco @firstdates_tv @Uber @cabify_espana Hoy en fisrt dates, precariedad en estado puro! Quien pagará la cena? <f0><U+009F><U+00A7><U+0090>"
## [5] "Nosotros cumpliendo las leyes día si y día también, y los piratas de #Uber y #cabify haciendo lo que les da la gana. Hace tiempo que ya estamos cansados de esta situación. Aeropuerto del Prat @aena, zona de salidas. Los @mossos ni están ni se les espera... Can picha. https://t.co/KYB263eTrh"
## [6] "Hola @cabify_espana tengo entendido que si soy un violador y un pedófilo ex presidiario, puedo trabajar con vosotros, que no hay ningún problema. Como lo hago? Tengo que hacer solo un curso de 1h verdad? #Cabify #Uber"
## [7] "@nunurob @Uber_ES A ver si tienes suerte y te lo devuelven Nuria, lo que hacen es una práctica habitual de estas empresas. Hay miles de denuncias en @LeaksUberCabify. Confía en el #taxi de siempre, legal y honrado y también tienen apps muy buenas. Saludos!"
## [8] "@oscar_herranz @airbnb_es @Uber @cabify_espana La economía global o el esclavismo del siglo XXI? <f0><U+009F><U+00A4><U+00A3> por cierto, ya veremos si se bloquean o no, este otoño o se bloquean esas apps o se bloquean las ciudades. A ver quien la tiene más grande <f0><U+009F><U+0098><U+0089>"
## [9] "@TAXIDRI87187936 @manowl @Uber_ES Si es amigo de nuestro enemigo, entonces no le ayudes. Que encima no da ni las gracias <f0><U+009F><U+0098><U+00AC> que se apañen las mierdas entre ellos <f0><U+009F><U+0098><U+008A>"
## [10] "Otra vez vuelve a pasar, un conductor de aplicación viola y mata a una chica joven #Uber #Cabify #Didi #VTC #Machismo https://t.co/A0SE53PGX8"
Quitamos las personas (@)
uber_txt <- gsub("@\\w+", "", uber_txt)
# Ahora veremos 5 tweets
head(uber_txt, 5)
## [1] "Y luego algunos sin materia gris andan defendiendo a #Uber y #Cabify. Pues aquí tenéis un claro ejemplo de lo que pasaría si el #Taxi dejara de prestar servicio. Ceporros, que os merecéis toda la mierda que tenéis, que no es poca. Españistán <f0><U+009F><U+0087><U+00AA><f0><U+009F><U+0087><U+00B8> https://t.co/s896P8ksDI"
## [2] " Esto no ha hecho más que empezar <ed><U+00A0><U+00BD><ed><U+00B1><U+008C>https://t.co/ILohDHTN1P"
## [3] "Yo si fuese un #violador, sin lugar a dudas me metía a trabajar en un #Uber #Cabify. Allí no me exigen nada y tengo muchas victimas donde elegir #cabifymola #deleteUber #QuienAvisaNoEsTraidor"
## [4] " Hoy en fisrt dates, precariedad en estado puro! Quien pagará la cena? <ed><U+00A0><U+00BE><ed><U+00B7><U+0090>"
## [5] "Nosotros cumpliendo las leyes día si y día también, y los piratas de #Uber y #cabify haciendo lo que les da la gana. Hace tiempo que ya estamos cansados de esta situación. Aeropuerto del Prat , zona de salidas. Los ni están ni se les espera... Can picha. https://t.co/KYB263eTrh"
Quitamos los links html
uber_txt <- gsub("\\bhttp[a-zA-Z0-9]*\\b", "", uber_txt)
head(uber_txt, 5)
## [1] "Y luego algunos sin materia gris andan defendiendo a #Uber y #Cabify. Pues aquí tenéis un claro ejemplo de lo que pasaría si el #Taxi dejara de prestar servicio. Ceporros, que os merecéis toda la mierda que tenéis, que no es poca. Españistán <ed><U+00A0><U+00BC><ed><U+00B7><U+00AA><ed><U+00A0><U+00BC><ed><U+00B7><U+00B8> ://t.co/s896P8ksDI"
## [2] " Esto no ha hecho más que empezar <ed><U+00A0><U+00BD><ed><U+00B1><U+008C>https://t.co/ILohDHTN1P"
## [3] "Yo si fuese un #violador, sin lugar a dudas me metía a trabajar en un #Uber #Cabify. Allí no me exigen nada y tengo muchas victimas donde elegir #cabifymola #deleteUber #QuienAvisaNoEsTraidor"
## [4] " Hoy en fisrt dates, precariedad en estado puro! Quien pagará la cena? <ed><U+00A0><U+00BE><ed><U+00B7><U+0090>"
## [5] "Nosotros cumpliendo las leyes día si y día también, y los piratas de #Uber y #cabify haciendo lo que les da la gana. Hace tiempo que ya estamos cansados de esta situación. Aeropuerto del Prat , zona de salidas. Los ni están ni se les espera... Can picha. ://t.co/KYB263eTrh"
Quitamos los caracteres no alfanuméricos
uber_txt <- gsub("[^a-zA-Z0-9 ]", "", uber_txt)
head(uber_txt, 5)
## [1] "Y luego algunos sin materia gris andan defendiendo a Uber y Cabify Pues aqu tenis un claro ejemplo de lo que pasara si el Taxi dejara de prestar servicio Ceporros que os merecis toda la mierda que tenis que no es poca Espaistn tcos896P8ksDI"
## [2] " Esto no ha hecho ms que empezar httpstcoILohDHTN1P"
## [3] "Yo si fuese un violador sin lugar a dudas me meta a trabajar en un Uber Cabify All no me exigen nada y tengo muchas victimas donde elegir cabifymola deleteUber QuienAvisaNoEsTraidor"
## [4] " Hoy en fisrt dates precariedad en estado puro Quien pagar la cena "
## [5] "Nosotros cumpliendo las leyes da si y da tambin y los piratas de Uber y cabify haciendo lo que les da la gana Hace tiempo que ya estamos cansados de esta situacin Aeropuerto del Prat zona de salidas Los ni estn ni se les espera Can picha tcoKYB263eTrh"
Quitamos la puntuación
uber_txt <- gsub("[[:punct:]]", "", uber_txt)
head(uber_txt, 5)
## [1] "Y luego algunos sin materia gris andan defendiendo a Uber y Cabify Pues aqu tenis un claro ejemplo de lo que pasara si el Taxi dejara de prestar servicio Ceporros que os merecis toda la mierda que tenis que no es poca Espaistn tcos896P8ksDI"
## [2] " Esto no ha hecho ms que empezar httpstcoILohDHTN1P"
## [3] "Yo si fuese un violador sin lugar a dudas me meta a trabajar en un Uber Cabify All no me exigen nada y tengo muchas victimas donde elegir cabifymola deleteUber QuienAvisaNoEsTraidor"
## [4] " Hoy en fisrt dates precariedad en estado puro Quien pagar la cena "
## [5] "Nosotros cumpliendo las leyes da si y da tambin y los piratas de Uber y cabify haciendo lo que les da la gana Hace tiempo que ya estamos cansados de esta situacin Aeropuerto del Prat zona de salidas Los ni estn ni se les espera Can picha tcoKYB263eTrh"
Quitamos la palabra amp. La palabra amp (esta palabra deberíamos intentar quitarla siempre en las correcciones / limpieza ).
uber_txt <- gsub("amp ", "", uber_txt)
head(uber_txt, 5)
## [1] "Y luego algunos sin materia gris andan defendiendo a Uber y Cabify Pues aqu tenis un claro ejemplo de lo que pasara si el Taxi dejara de prestar servicio Ceporros que os merecis toda la mierda que tenis que no es poca Espaistn tcos896P8ksDI"
## [2] " Esto no ha hecho ms que empezar httpstcoILohDHTN1P"
## [3] "Yo si fuese un violador sin lugar a dudas me meta a trabajar en un Uber Cabify All no me exigen nada y tengo muchas victimas donde elegir cabifymola deleteUber QuienAvisaNoEsTraidor"
## [4] " Hoy en fisrt dates precariedad en estado puro Quien pagar la cena "
## [5] "Nosotros cumpliendo las leyes da si y da tambin y los piratas de Uber y cabify haciendo lo que les da la gana Hace tiempo que ya estamos cansados de esta situacin Aeropuerto del Prat zona de salidas Los ni estn ni se les espera Can picha tcoKYB263eTrh"
Quitamos los tco. Los tco son un servicio que se usan para cortar los links
uber_txt <- gsub("\\btco[a-zA-Z0-9]*\\b", "", uber_txt)
head(uber_txt, 5)
## [1] "Y luego algunos sin materia gris andan defendiendo a Uber y Cabify Pues aqu tenis un claro ejemplo de lo que pasara si el Taxi dejara de prestar servicio Ceporros que os merecis toda la mierda que tenis que no es poca Espaistn "
## [2] " Esto no ha hecho ms que empezar httpstcoILohDHTN1P"
## [3] "Yo si fuese un violador sin lugar a dudas me meta a trabajar en un Uber Cabify All no me exigen nada y tengo muchas victimas donde elegir cabifymola deleteUber QuienAvisaNoEsTraidor"
## [4] " Hoy en fisrt dates precariedad en estado puro Quien pagar la cena "
## [5] "Nosotros cumpliendo las leyes da si y da tambin y los piratas de Uber y cabify haciendo lo que les da la gana Hace tiempo que ya estamos cansados de esta situacin Aeropuerto del Prat zona de salidas Los ni estn ni se les espera Can picha "
Quitamos NAs
uber_txt <- uber_txt[!is.na(uber_txt)]
head(uber_txt, 5)
## [1] "Y luego algunos sin materia gris andan defendiendo a Uber y Cabify Pues aqu tenis un claro ejemplo de lo que pasara si el Taxi dejara de prestar servicio Ceporros que os merecis toda la mierda que tenis que no es poca Espaistn "
## [2] " Esto no ha hecho ms que empezar httpstcoILohDHTN1P"
## [3] "Yo si fuese un violador sin lugar a dudas me meta a trabajar en un Uber Cabify All no me exigen nada y tengo muchas victimas donde elegir cabifymola deleteUber QuienAvisaNoEsTraidor"
## [4] " Hoy en fisrt dates precariedad en estado puro Quien pagar la cena "
## [5] "Nosotros cumpliendo las leyes da si y da tambin y los piratas de Uber y cabify haciendo lo que les da la gana Hace tiempo que ya estamos cansados de esta situacin Aeropuerto del Prat zona de salidas Los ni estn ni se les espera Can picha "
Quitamos emoticonos
uber_txt <- iconv(uber_txt, 'UTF-8', 'ASCII')
head(uber_txt, 5)
## [1] "Y luego algunos sin materia gris andan defendiendo a Uber y Cabify Pues aqu tenis un claro ejemplo de lo que pasara si el Taxi dejara de prestar servicio Ceporros que os merecis toda la mierda que tenis que no es poca Espaistn "
## [2] " Esto no ha hecho ms que empezar httpstcoILohDHTN1P"
## [3] "Yo si fuese un violador sin lugar a dudas me meta a trabajar en un Uber Cabify All no me exigen nada y tengo muchas victimas donde elegir cabifymola deleteUber QuienAvisaNoEsTraidor"
## [4] " Hoy en fisrt dates precariedad en estado puro Quien pagar la cena "
## [5] "Nosotros cumpliendo las leyes da si y da tambin y los piratas de Uber y cabify haciendo lo que les da la gana Hace tiempo que ya estamos cansados de esta situacin Aeropuerto del Prat zona de salidas Los ni estn ni se les espera Can picha "
Limpieza de espacios, tabuladores, etc.
uber_txt <- gsub("[ \t]{2,}", "", uber_txt)
uber_txt <- gsub("^\\s+|\\s+$", "", uber_txt)
head(uber_txt, 5)
## [1] "Y luego algunos sin materia gris andan defendiendo a Uber y Cabify Pues aqu tenis un claro ejemplo de lo que pasara si el Taxi dejara de prestar servicio Ceporros que os merecis toda la mierda que tenis que no es poca Espaistn"
## [2] "Esto no ha hecho ms que empezar httpstcoILohDHTN1P"
## [3] "Yo si fuese un violador sin lugar a dudas me meta a trabajar en un Uber Cabify All no me exigen nada y tengo muchas victimas donde elegir cabifymola deleteUber QuienAvisaNoEsTraidor"
## [4] "Hoy en fisrt dates precariedad en estado puro Quien pagar la cena"
## [5] "Nosotros cumpliendo las leyes da si y da tambin y los piratas de Uber y cabify haciendo lo que les da la gana Hace tiempo que ya estamos cansados de esta situacin Aeropuerto del Pratzona de salidas Losni estn ni se les espera Can picha"
Pasamos a minúsculas todo el texto
uber_txt <- tolower(uber_txt)
head(uber_txt, 5)
## [1] "y luego algunos sin materia gris andan defendiendo a uber y cabify pues aqu tenis un claro ejemplo de lo que pasara si el taxi dejara de prestar servicio ceporros que os merecis toda la mierda que tenis que no es poca espaistn"
## [2] "esto no ha hecho ms que empezar httpstcoilohdhtn1p"
## [3] "yo si fuese un violador sin lugar a dudas me meta a trabajar en un uber cabify all no me exigen nada y tengo muchas victimas donde elegir cabifymola deleteuber quienavisanoestraidor"
## [4] "hoy en fisrt dates precariedad en estado puro quien pagar la cena"
## [5] "nosotros cumpliendo las leyes da si y da tambin y los piratas de uber y cabify haciendo lo que les da la gana hace tiempo que ya estamos cansados de esta situacin aeropuerto del pratzona de salidas losni estn ni se les espera can picha"
Vemos como nos ha quedado el texto y lo comparamos con el original antes de realizar toda la limpieza. Primero el original.
# head(sapply(uber_tweets, function(x) x$getText()), 10)
head(uber_tweets$text, 5)
## [1] "Y luego algunos sin materia gris andan defendiendo a #Uber y #Cabify. Pues aquí tenéis un claro ejemplo de lo que pasaría si el #Taxi dejara de prestar servicio. Ceporros, que os merecéis toda la mierda que tenéis, que no es poca. Españistán <f0><U+009F><U+0087><U+00AA><f0><U+009F><U+0087><U+00B8> https://t.co/s896P8ksDI"
## [2] "@boye_g @loputosatir Esto no ha hecho más que empezar <f0><U+009F><U+0091><U+008C>https://t.co/ILohDHTN1P"
## [3] "Yo si fuese un #violador, sin lugar a dudas me metía a trabajar en un #Uber #Cabify. Allí no me exigen nada y tengo muchas victimas donde elegir #cabifymola #deleteUber #QuienAvisaNoEsTraidor"
## [4] "@PesetoLoco @firstdates_tv @Uber @cabify_espana Hoy en fisrt dates, precariedad en estado puro! Quien pagará la cena? <f0><U+009F><U+00A7><U+0090>"
## [5] "Nosotros cumpliendo las leyes día si y día también, y los piratas de #Uber y #cabify haciendo lo que les da la gana. Hace tiempo que ya estamos cansados de esta situación. Aeropuerto del Prat @aena, zona de salidas. Los @mossos ni están ni se les espera... Can picha. https://t.co/KYB263eTrh"
Y el limpio
head(uber_txt, 5)
## [1] "y luego algunos sin materia gris andan defendiendo a uber y cabify pues aqu tenis un claro ejemplo de lo que pasara si el taxi dejara de prestar servicio ceporros que os merecis toda la mierda que tenis que no es poca espaistn"
## [2] "esto no ha hecho ms que empezar httpstcoilohdhtn1p"
## [3] "yo si fuese un violador sin lugar a dudas me meta a trabajar en un uber cabify all no me exigen nada y tengo muchas victimas donde elegir cabifymola deleteuber quienavisanoestraidor"
## [4] "hoy en fisrt dates precariedad en estado puro quien pagar la cena"
## [5] "nosotros cumpliendo las leyes da si y da tambin y los piratas de uber y cabify haciendo lo que les da la gana hace tiempo que ya estamos cansados de esta situacin aeropuerto del pratzona de salidas losni estn ni se les espera can picha"
Vemos como hemos quitado la puntuación, links o emoticonos, entre otros. Una vez limpiado el texto podemos empezar a trabajar.
Es necesario hacer un Corpus de tm para realizar otras operaciones de minería de texto.
uber_corpus <- Corpus(VectorSource(uber_txt))
inspect(uber_corpus[1:10])
## <<SimpleCorpus>>
## Metadata: corpus specific: 1, document level (indexed): 0
## Content: documents: 10
##
## [1] y luego algunos sin materia gris andan defendiendo a uber y cabify pues aqu tenis un claro ejemplo de lo que pasara si el taxi dejara de prestar servicio ceporros que os merecis toda la mierda que tenis que no es poca espaistn
## [2] esto no ha hecho ms que empezar httpstcoilohdhtn1p
## [3] yo si fuese un violador sin lugar a dudas me meta a trabajar en un uber cabify all no me exigen nada y tengo muchas victimas donde elegir cabifymola deleteuber quienavisanoestraidor
## [4] hoy en fisrt dates precariedad en estado puro quien pagar la cena
## [5] nosotros cumpliendo las leyes da si y da tambin y los piratas de uber y cabify haciendo lo que les da la gana hace tiempo que ya estamos cansados de esta situacin aeropuerto del pratzona de salidas losni estn ni se les espera can picha
## [6] holatengo entendido que si soy un violador y un pedfilo ex presidiario puedo trabajar con vosotros que no hay ningn problema como lo hago tengo que hacer solo un curso de 1h verdad cabify uber
## [7] a ver si tienes suerte y te lo devuelven nuria lo que hacen es una prctica habitual de estas empresas hay miles de denuncias enconfa en el taxi de siempre legal y honrado y tambin tienen apps muy buenas saludos
## [8] la economa global o el esclavismo del siglo xxipor cierto ya veremos si se bloquean o no este otoo o se bloquean esas apps o se bloquean las ciudades a ver quien la tiene ms grande
## [9] si es amigo de nuestro enemigo entonces no le ayudes que encima no da ni las graciasque se apaen las mierdas entre ellos
## [10] otra vez vuelve a pasar un conductor de aplicacin viola y mata a una chica joven uber cabify didi vtc machismo
Al igual que se puede limpiar el texto con gsub, podemos limpiar el corpus con tm_map. En este chunk aplicamos la transformación a minúsculas, eliminación de números, puntuación, palabras comunes (stopwords) y espacios en blanco.
Ahora vamos a usar la función tm_map para mejorar el corpus y guardarlo en un nuevo objeto, uber_corpus_clean. Esta función tiene distintas posibilidades. Empezamos por pasar el texto a minúsculas y quitar los números
# Pasamos a minusculas
uber_corpus_clean <- tm_map(uber_corpus, tolower)
## Warning in tm_map.SimpleCorpus(uber_corpus, tolower): transformation drops
## documents
# Eliminamos los numeros
uber_corpus_clean <- tm_map(uber_corpus_clean, removeNumbers)
## Warning in tm_map.SimpleCorpus(uber_corpus_clean, removeNumbers):
## transformation drops documents
# Eliminamos la puntuacion
uber_corpus_clean <- tm_map(uber_corpus_clean, removePunctuation)
## Warning in tm_map.SimpleCorpus(uber_corpus_clean, removePunctuation):
## transformation drops documents
# Eliminamos los espacios en blanco
uber_corpus_clean <- tm_map(uber_corpus_clean, stripWhitespace)
## Warning in tm_map.SimpleCorpus(uber_corpus_clean, stripWhitespace):
## transformation drops documents
Como hemos visto el paquete tm nos proporciona la posibilidad de eliminar un grupo de palabras del corpus, limpiando el texto. Entre esas funciones, una de las más importante es stopwords(). Esta funcion nos permite eliminar palabras que se utilizan comunmente en el lenguaja, como articulos o preposiciones.
En español también podemos ver las palabras comunes y eliminarlas. Vemos las palabras incluidas en la función
stopwords(kind='es')
## [1] "de" "la" "que" "el"
## [5] "en" "y" "a" "los"
## [9] "del" "se" "las" "por"
## [13] "un" "para" "con" "no"
## [17] "una" "su" "al" "lo"
## [21] "como" "más" "pero" "sus"
## [25] "le" "ya" "o" "este"
## [29] "sí" "porque" "esta" "entre"
## [33] "cuando" "muy" "sin" "sobre"
## [37] "también" "me" "hasta" "hay"
## [41] "donde" "quien" "desde" "todo"
## [45] "nos" "durante" "todos" "uno"
## [49] "les" "ni" "contra" "otros"
## [53] "ese" "eso" "ante" "ellos"
## [57] "e" "esto" "mí" "antes"
## [61] "algunos" "qué" "unos" "yo"
## [65] "otro" "otras" "otra" "él"
## [69] "tanto" "esa" "estos" "mucho"
## [73] "quienes" "nada" "muchos" "cual"
## [77] "poco" "ella" "estar" "estas"
## [81] "algunas" "algo" "nosotros" "mi"
## [85] "mis" "tú" "te" "ti"
## [89] "tu" "tus" "ellas" "nosotras"
## [93] "vosotros" "vosotras" "os" "mío"
## [97] "mía" "míos" "mías" "tuyo"
## [101] "tuya" "tuyos" "tuyas" "suyo"
## [105] "suya" "suyos" "suyas" "nuestro"
## [109] "nuestra" "nuestros" "nuestras" "vuestro"
## [113] "vuestra" "vuestros" "vuestras" "esos"
## [117] "esas" "estoy" "estás" "está"
## [121] "estamos" "estáis" "están" "esté"
## [125] "estés" "estemos" "estéis" "estén"
## [129] "estaré" "estarás" "estará" "estaremos"
## [133] "estaréis" "estarán" "estaría" "estarías"
## [137] "estaríamos" "estaríais" "estarían" "estaba"
## [141] "estabas" "estábamos" "estabais" "estaban"
## [145] "estuve" "estuviste" "estuvo" "estuvimos"
## [149] "estuvisteis" "estuvieron" "estuviera" "estuvieras"
## [153] "estuviéramos" "estuvierais" "estuvieran" "estuviese"
## [157] "estuvieses" "estuviésemos" "estuvieseis" "estuviesen"
## [161] "estando" "estado" "estada" "estados"
## [165] "estadas" "estad" "he" "has"
## [169] "ha" "hemos" "habéis" "han"
## [173] "haya" "hayas" "hayamos" "hayáis"
## [177] "hayan" "habré" "habrás" "habrá"
## [181] "habremos" "habréis" "habrán" "habría"
## [185] "habrías" "habríamos" "habríais" "habrían"
## [189] "había" "habías" "habíamos" "habíais"
## [193] "habían" "hube" "hubiste" "hubo"
## [197] "hubimos" "hubisteis" "hubieron" "hubiera"
## [201] "hubieras" "hubiéramos" "hubierais" "hubieran"
## [205] "hubiese" "hubieses" "hubiésemos" "hubieseis"
## [209] "hubiesen" "habiendo" "habido" "habida"
## [213] "habidos" "habidas" "soy" "eres"
## [217] "es" "somos" "sois" "son"
## [221] "sea" "seas" "seamos" "seáis"
## [225] "sean" "seré" "serás" "será"
## [229] "seremos" "seréis" "serán" "sería"
## [233] "serías" "seríamos" "seríais" "serían"
## [237] "era" "eras" "éramos" "erais"
## [241] "eran" "fui" "fuiste" "fue"
## [245] "fuimos" "fuisteis" "fueron" "fuera"
## [249] "fueras" "fuéramos" "fuerais" "fueran"
## [253] "fuese" "fueses" "fuésemos" "fueseis"
## [257] "fuesen" "siendo" "sido" "tengo"
## [261] "tienes" "tiene" "tenemos" "tenéis"
## [265] "tienen" "tenga" "tengas" "tengamos"
## [269] "tengáis" "tengan" "tendré" "tendrás"
## [273] "tendrá" "tendremos" "tendréis" "tendrán"
## [277] "tendría" "tendrías" "tendríamos" "tendríais"
## [281] "tendrían" "tenía" "tenías" "teníamos"
## [285] "teníais" "tenían" "tuve" "tuviste"
## [289] "tuvo" "tuvimos" "tuvisteis" "tuvieron"
## [293] "tuviera" "tuvieras" "tuviéramos" "tuvierais"
## [297] "tuvieran" "tuviese" "tuvieses" "tuviésemos"
## [301] "tuvieseis" "tuviesen" "teniendo" "tenido"
## [305] "tenida" "tenidos" "tenidas" "tened"
La siguiente línea le dice a la función tm_map que elimine las palabras (removeWords) de corpus_clean que están en stopwords() del listado de palabras españolas.
uber_corpus_clean <- tm_map(uber_corpus_clean, removeWords, stopwords(kind = "es"))
## Warning in tm_map.SimpleCorpus(uber_corpus_clean, removeWords,
## stopwords(kind = "es")): transformation drops documents
Ahora podemos hacer un Document-Term Matrix (dtm) y un Term Document Matrix (tdm)
uber_tdm <- TermDocumentMatrix(uber_corpus_clean, control = list(stopwords = TRUE))
uber_tdm <- as.matrix(uber_tdm)
Hacemos un dtm para ver cuantas veces aparecen las palabras en el documento.
uber_dtm <- DocumentTermMatrix(uber_corpus_clean, control = list(minWordLength = 1, stopwords = TRUE))
inspect(uber_dtm)
## <<DocumentTermMatrix (documents: 1771, terms: 6185)>>
## Non-/sparse entries: 18164/10935471
## Sparsity : 100%
## Maximal term length: 62
## Weighting : term frequency (tf)
## Sample :
## Terms
## Docs autnomos cabify coches efectivo invierte madrid millones taxi
## 1042 0 0 0 0 0 0 0 0
## 1048 0 1 0 0 0 0 0 1
## 1081 0 1 0 0 0 0 0 0
## 1222 0 1 0 0 0 0 0 0
## 1456 0 0 0 0 0 0 0 1
## 1559 0 0 0 0 0 1 0 0
## 1747 0 1 0 0 0 0 0 0
## 512 0 0 1 0 1 0 1 0
## 805 0 0 0 0 0 0 0 2
## 861 0 0 0 0 0 0 0 0
## Terms
## Docs toyota uber
## 1042 0 2
## 1048 0 1
## 1081 0 1
## 1222 0 1
## 1456 0 1
## 1559 0 0
## 1747 0 1
## 512 3 3
## 805 0 1
## 861 0 0
En el caso del DTM vemos cuantas veces se repiten las palabras.
El stem es util para sacar la raíz de las palabras.
uber_corpus_stem <- tm_map(uber_corpus_clean, stemDocument)
## Warning in tm_map.SimpleCorpus(uber_corpus_clean, stemDocument):
## transformation drops documents
uber_corpus_stem <- tm_map(uber_corpus_stem, stemCompletion, dictionary = uber_corpus_clean)
## Warning in tm_map.SimpleCorpus(uber_corpus_stem, stemCompletion, dictionary
## = uber_corpus_clean): transformation drops documents
inspect(uber_corpus_stem[1:5])
## <<SimpleCorpus>>
## Metadata: corpus specific: 1, document level (indexed): 0
## Content: documents: 5
##
## luego materia gris andan defendiendo uber cabifi pue aqu teni claro ejemplo pasara si taxi dejara prestar servicio ceporro mereci toda mierda teni poca espaistn
##
## hecho ms empezar httpstcoilohdhtnp
##
## si violador lugar duda meta trabajar uber cabifi all exigen mucha victima elegir cabifymola deleteub quienavisanoestraidor
##
## hoy fisrt date precariedad puro pagar cena
##
## cumpliendo ley da si da tambin pirata uber cabifi haciendo da gana hace tiempo cansado situacin aeropuerto pratzona salida losni estn espera can picha
##
Términos más frecuentes frecuentes. Ponemos la frecuencia mínima 10 y ponemos en un “head” que nos devuelva los 40 primeros.
head(findFreqTerms(uber_dtm, lowfreq=10), 40)
## [1] "aqu" "cabify" "claro" "luego" "mierda"
## [6] "pues" "servicio" "taxi" "uber" "lugar"
## [11] "muchas" "trabajar" "hoy" "pagar" "aeropuerto"
## [16] "espera" "estn" "gana" "hace" "haciendo"
## [21] "tambin" "tiempo" "hacer" "ningn" "problema"
## [26] "puedo" "solo" "verdad" "apps" "denuncias"
## [31] "empresas" "hacen" "siempre" "ver" "cierto"
## [36] "ciudades" "economa" "encima" "enemigo" "aplicacin"
Vemos como tiene sentido que aparezcan muchas de estas palabras dentro de los tweets relacionados con la empresa estadounidense que ofrece servicios de transporte, siendo los tweets capturados aquellos que han sido escritos en español y en la geografia española. Entre estas palabras se encuentran: taxistas, ley, madrid, demandaran, cabify o tribunal.
Vamos a ver qué palabras están mas asociadas a la palabra cabify.
findAssocs(uber_dtm, 'cabify', 0.40)
## $cabify
## numeric(0)
Vemos que las palabras asociadas con cabify que son mas repetidas son vtc, economiacolaborativa, legislacion, facturacion o taxi.
Ahora vamos a crear un diccionario con las palabras con un número mínimo de apariciones de 5. Aunque antes existia una funcion concreta (Dictionary), esta funcion ya no existe.
Creamos una función
Dictionary <- function(x) {
if( is.character(x) ) {
return (x)
}
stop('x is not a character vector')
}
La aplicamos en el dtm
uber_dict <- Dictionary(findFreqTerms(uber_dtm, 5))
head(uber_dict)
## [1] "aqu" "cabify" "claro" "ejemplo" "luego" "mierda"
library(wordcloud)
wordcloud(uber_corpus_clean, min.freq = 10, random.order = FALSE)
Ahora que tenemos el texto limpio para el análisis, podemos hacer análisis de opinión y sentimiento. La función classify_emotion “clasifica la emoción (por ejemplo, enfado, disgusto, miedo, alegría, tristeza o sorpresa) de un conjunto de textos usando un clasificador de Bayes entrenado en el”vocabulario de emociones“”.
Empezamos clasificando emociones con classify_emotion usando un algoritmo de bayes. Para saber mas podemos ejecutar directamente la ayuda para saber lo que hace.
?classify_emotion
## starting httpd help server ... done
Como se describe en la ayuda, esta función clasifica emociones (e.g. anger, disgust, fear, joy, sadness, surprise) de una serie de textos.
uber_class_emo <- classify_emotion(uber_txt, algorithm="bayes", prior=1.0)
La función nos retorna 7 columnas: anger, disgust, fear, joy, sadness, surprise y best_fit para cada fila del documento
head(uber_class_emo)
## ANGER DISGUST FEAR
## [1,] "1.46871776464786" "3.09234031207392" "2.06783599555953"
## [2,] "1.46871776464786" "3.09234031207392" "2.06783599555953"
## [3,] "1.46871776464786" "3.09234031207392" "2.06783599555953"
## [4,] "1.46871776464786" "3.09234031207392" "2.06783599555953"
## [5,] "1.46871776464786" "3.09234031207392" "2.06783599555953"
## [6,] "7.34083555412328" "3.09234031207392" "2.06783599555953"
## JOY SADNESS SURPRISE BEST_FIT
## [1,] "1.02547755260094" "1.7277074477352" "2.78695866252273" NA
## [2,] "1.02547755260094" "1.7277074477352" "2.78695866252273" NA
## [3,] "1.02547755260094" "1.7277074477352" "2.78695866252273" NA
## [4,] "1.02547755260094" "1.7277074477352" "2.78695866252273" NA
## [5,] "1.02547755260094" "1.7277074477352" "2.78695866252273" NA
## [6,] "1.02547755260094" "1.7277074477352" "2.78695866252273" "anger"
Ahora lo que vamos a hacer es crear una variable denominada “emotion” en la que guardemos los resultados que ha obtenido el algoritmo de forma ordenada. La que según el algoritmo encaja mejor (BEST_FIT) la guardamos.
Para facilitar la clasificación, vamos a substituir los NAs por unknown.
emotion <- uber_class_emo[, 7]
emotion[is.na(emotion)] <- "unknown"
table(emotion, useNA = "ifany")
## emotion
## anger fear joy sadness surprise unknown
## 298 38 92 21 4 1318
Veamos los sentimientos en un gráfico. Para ello tenemos que convertirlo en un data.frame.
library(ggplot2)
library(gridExtra)
uber_pie <- ggplot(as.data.frame(uber_class_emo), aes(x = factor(1), fill = factor(BEST_FIT))) + geom_bar(width = 1)
uber_pie + coord_polar(theta = "y") + ggtitle("Sentimiento Uber en España", subtitle = "Datos España") + ylab("Y") + xlab("X") + theme(plot.title = element_text(size=12, face='bold'))
Ahora veamos quitando los NA
library(ggplot2)
library(gridExtra)
uber_pie <- ggplot(as.data.frame(uber_class_emo), aes(x = factor(1), fill = factor(BEST_FIT))) + geom_bar(width = 1)
uber_pie + coord_polar(theta = "y") + ggtitle("Sentimiento Uber en España", subtitle = "Datos España") + ylab("Y") + xlab("X") + scale_fill_brewer(palette = "RdYlGn") + theme(plot.title = element_text(size=12, face='bold'))
Ahora pasamos a ver otra clasificación, que es la de polaridad. Ahora obtenemos la polaridad. Clasificamos el texto en cuatro categorías:
Podemos volver a ejecutar la ayuda para conocer como trabaja esta función. ?classify_polarity
Ejecutamos la función de clasificación de polaridad.
uber_class_pol <- classify_polarity(uber_txt, algorithm="bayes")
head(uber_class_pol, 5)
## POS NEG POS/NEG
## [1,] "1.03127774142571" "26.8423564950873" "0.0384197915564697"
## [2,] "1.03127774142571" "0.445453222112551" "2.31512017476245"
## [3,] "1.03127774142571" "9.47547003995745" "0.108836578774127"
## [4,] "1.03127774142571" "0.445453222112551" "2.31512017476245"
## [5,] "8.78232285939751" "0.445453222112551" "19.7154772340574"
## BEST_FIT
## [1,] "negative"
## [2,] "positive"
## [3,] "negative"
## [4,] "positive"
## [5,] "positive"
Ahora guardamos con la variable polarity los resultados obtenidos de la columna “BEST_FIT”. Esto nos permitirá conocer hacia donde se inclina la balanza, bien hacia comentarios positivos o negativos.
polarity <- uber_class_pol[, 4]
head(polarity)
## [1] "negative" "positive" "negative" "positive" "positive" "negative"
En una tabla
table(polarity, useNA = 'ifany')
## polarity
## negative neutral positive
## 382 84 1305
La mayoria de los comentarios parecen ser positivos.
Podemos recopilar la información en un dataframe por si más adelante queremos utilizarlo. Lo clasificamos en texto, emoción y polaridad.
uber_sentiment_dataframe <- data.frame(text=uber_txt, emotion=emotion,
polarity=polarity, stringsAsFactors=FALSE)
head(uber_sentiment_dataframe, 5)
Echemos un vistazo a algunas caracteristicas de este dataframe
Nombres de las variables
names(uber_sentiment_dataframe)
## [1] "text" "emotion" "polarity"
Estructura del dataframe
str(uber_sentiment_dataframe)
## 'data.frame': 1771 obs. of 3 variables:
## $ text : chr "y luego algunos sin materia gris andan defendiendo a uber y cabify pues aqu tenis un claro ejemplo de lo que pa"| __truncated__ "esto no ha hecho ms que empezar httpstcoilohdhtn1p" "yo si fuese un violador sin lugar a dudas me meta a trabajar en un uber cabify all no me exigen nada y tengo mu"| __truncated__ "hoy en fisrt dates precariedad en estado puro quien pagar la cena" ...
## $ emotion : chr "unknown" "unknown" "unknown" "unknown" ...
## $ polarity: chr "negative" "positive" "negative" "positive" ...
Resumen del dataframe
summary(uber_sentiment_dataframe)
## text emotion polarity
## Length:1771 Length:1771 Length:1771
## Class :character Class :character Class :character
## Mode :character Mode :character Mode :character
Reordenamos por emociones y polaridad.
uber_sentiment_dataframe <- within(uber_sentiment_dataframe, emotion <- factor(emotion, levels=names(sort(table(emotion), decreasing=TRUE))))
head(uber_sentiment_dataframe)
Número de Tweets clasificados por categorías de emociones
ggplot(uber_sentiment_dataframe, aes(x=emotion)) + geom_bar(aes(y=..count.., fill=emotion)) +
scale_fill_brewer(palette="Dark2") +
ggtitle("Análisis de sentimiento de Uber en Twitter", subtitle = "Datos Uber España") +
theme(legend.position="right", plot.title = element_text(size=12, face='bold')) + ylab("Número de Tweets") + xlab("Tipos de emoción")
Gráfico de Polaridad por tweets
ggplot(uber_sentiment_dataframe, aes(x=polarity)) +
geom_bar(aes(y=..count.., fill=polarity)) +
scale_fill_brewer(palette="RdYlBu") +
ggtitle("Análisis de sentimiento Uber en Twitter", subtitle = "Datos España") +
theme(legend.position="bottom", plot.title = element_text(size=12, face='bold')) + ylab("Número de Tweets") + xlab("Tipos de polaridad")
Finalmente, veamos las palabras en los tweets y creamos una nube de palabras que usa las emociones de las palabras para determinar su ubicación dentro de la nube.
uber_sentiment_df = data.frame(text=uber_txt, emotion=emotion,
polarity=polarity, stringsAsFactors=FALSE)
# Separamos el texto segun las emociones
emotion_uber = levels(factor(uber_sentiment_df$emotion))
emotion_length = length(emotion_uber)
emotion_uber.docs = rep('', emotion_length)
for (i in 1: emotion_length)
{
tmp = uber_txt[emotion == emotion_uber[i]]
emotion_uber.docs[i] = paste(tmp, collapse=' ')
}
# Eliminamos las Stopwords
emotion_uber.docs = removeWords(emotion_uber.docs, stopwords('es'))
# Creamos el corpus
corpus = Corpus(VectorSource(emotion_uber.docs))
tdm = TermDocumentMatrix(corpus)
tdm = as.matrix(tdm)
colnames(tdm) = emotion_uber
# Dibujamos una Comparison Wordcloud
comparison.cloud(tdm, colors = brewer.pal(emotion_length, 'Dark2'),
scale = c(1,.2), max.words = 400,random.order = FALSE, title.size = 1.5)
### Cerramos sesión
La función sessionInfo() nos sirve para ver los datos que hemos utilizado, para ver que datos están cargados, cuales eran los paquetes instalados. Esto nos sirve muchas veces para poder trazar lo que hemos hecho y ver errores posibles en el código.
# Terminamos la sesión con
sessionInfo()
## R version 3.4.4 (2018-03-15)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 17134)
##
## Matrix products: default
##
## locale:
## [1] LC_COLLATE=Spanish_Spain.1252 LC_CTYPE=Spanish_Spain.1252
## [3] LC_MONETARY=Spanish_Spain.1252 LC_NUMERIC=C
## [5] LC_TIME=Spanish_Spain.1252
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] gridExtra_2.3 sentiment_0.2 Rstem_0.4-1
## [4] tm_0.7-5 NLP_0.1-11 ggplot2_3.0.0
## [7] plyr_1.8.4 wordcloud_2.6 RColorBrewer_1.1-2
## [10] rtweet_0.6.7.9000
##
## loaded via a namespace (and not attached):
## [1] Rcpp_0.12.18 compiler_3.4.4 pillar_1.3.0 bindr_0.1.1
## [5] tools_3.4.4 digest_0.6.16 jsonlite_1.5 evaluate_0.11
## [9] tibble_1.4.2 gtable_0.2.0 pkgconfig_2.0.2 rlang_0.2.1
## [13] curl_3.2 parallel_3.4.4 yaml_2.2.0 bindrcpp_0.2.2
## [17] xml2_1.2.0 withr_2.1.2 httr_1.3.1 stringr_1.3.1
## [21] dplyr_0.7.6 knitr_1.20 rprojroot_1.3-2 grid_3.4.4
## [25] tidyselect_0.2.4 glue_1.3.0 R6_2.2.2 rmarkdown_1.10
## [29] purrr_0.2.5 magrittr_1.5 SnowballC_0.5.1 backports_1.1.2
## [33] scales_1.0.0 htmltools_0.3.6 assertthat_0.2.0 colorspace_1.3-2
## [37] labeling_0.3 stringi_1.1.7 openssl_1.0.2 lazyeval_0.2.1
## [41] munsell_0.5.0 slam_0.1-43 crayon_1.3.4