Análisis de Sentimiento con R
Definiciones
Carga de Bibliotecas
Para practicar técnicas de procesamiento y análisis computacional de textos, vamos a trabajar con un dataset de letras de tango. La información fue recopilada a partir de las letras publicadas en el sitio Todo Tango, por el Dr. Germán Rosatti.
Veamos una sítesis del corpus de conocimiento que cargamos
link titulo ritmo ano
Length:10056 Length:10056 Length:10056 Length:10056
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
musica compositor letra
Length:10056 Length:10056 Length:10056
Class :character Class :character Class :character
Mode :character Mode :character Mode :character
Examinemos la cabecera de la tabla
# A tibble: 6 x 7
link titulo ritmo ano musica compositor letra
<chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 http://www.tod… a bailar tango 1943 domingo… homero exp… "a bailar a bail…
2 http://www.tod… a bailar… tango 1962 leopold… leopoldo d… "este tango naci…
3 http://www.tod… a bailar… tango vacio jose da… vacio <NA>
4 http://www.tod… a beba b… poema … vacio vacio alberto ue… "nacio en la cal…
5 http://www.tod… a belisa… tango vacio enrique… vacio <NA>
6 http://www.tod… a bordo … milonga vacio cesar i… eugenio ma… "camine todas la…
Agregamos una columna con la década de cada tanto, usando un truquito aritmético. Si a cualquier año se le sustrae el resto de una división entera por 10, el resultado es la década correspondiente a ese año. Por ejemplo, el resto de 1928 / 10 es 8 , y 1928 - 8 = 1920. En informática, la función que devuelve el resto de una división entera suele llamarse módulo. En R, el módulo se invoca con %%.
Creamos nuestra columna de décadas
Notése que en la mayoría de los casos no se registra el año del tango, por lo que tampoco obtenemos la década.
# A tibble: 14 x 2
decada n
<dbl> <int>
1 NA 7179
2 1940 593
3 1930 541
4 1920 435
5 1950 256
6 2000 197
7 1960 194
8 2010 166
9 1980 162
10 1970 122
11 1910 101
12 1990 92
13 1900 17
14 1890 1
Graficamos la cantidad de tangos encontrados por década
Sabiendo poco de tango, voy a asumir que de los años ’20 a los ’40 transcurrió la era dorada del género.
También podemos revisar la distribución por género.
# A tibble: 93 x 2
ritmo n
<chr> <int>
1 tango 7208
2 vals 919
3 milonga 733
4 poema lunfardo 273
5 cancion 214
6 none 88
7 ranchera 72
8 zamba 61
9 candombe 53
10 arr en tango 42
# … with 83 more rows
Y realizar un ranking de los compositores más prolíficos (o al menos, los más representados en el dataset). Nuevamente se trata de una variable con mayoría de datos faltantes.
# A tibble: 1,669 x 2
compositor n
<chr> <int>
1 vacio 2035
2 enrique cadicamo 203
3 celedonio flores 118
4 homero manzi 113
5 carlos bahr 102
6 catulo castillo 93
7 francisco garcia jimenez 91
8 hector negro 85
9 horacio ferrer 85
10 reinaldo yiso 83
# … with 1,659 more rows
Tokenizado
Preparando los datos para análisis de texto: la “tokenización” En la jerga del análisis computacional de texto se le llama “tokenizar” (por tokenize en inglés) al acto de extraer unidades de análisis a partir de un cuerpo de escritos. Cualquiera sea el material analizado (frases, discursos o libros completos) se le extrae las palabras individuales que lo componen (“tokens”) para luego cuantificar de algún modo sus atributos.
En nuestro dataset la letra de los tangos aparece en un sólo campo, con las oraciones separadas a veces por uan barra vertical (“|”) y en ocasiones por la secuencia “”. Podemos usar separate_rows, una función que permite reorganizar una variable de modo que cada observacion se distribuya en múltiples filas, separando el valor original en base a un delimitador especificado. Usamos entonces sep_rows , con el parámetro “sep” indicando cuales son los separadores, y luego agregamos una variable nueva que ennumere las líneas de cada tango:
# A tibble: 6 x 9
link titulo ritmo ano musica compositor letra decada linea
<chr> <chr> <chr> <int> <chr> <chr> <chr> <dbl> <int>
1 http://www.to… a bail… tango 1943 domingo… homero ex… "a bailar… 1940 1
2 http://www.to… a bail… tango 1943 domingo… homero ex… " que la … 1940 2
3 http://www.to… a bail… tango 1943 domingo… homero ex… " sobre e… 1940 3
4 http://www.to… a bail… tango 1943 domingo… homero ex… " de un t… 1940 4
5 http://www.to… a bail… tango 1943 domingo… homero ex… " se ira … 1940 5
6 http://www.to… a bail… tango 1943 domingo… homero ex… " a baila… 1940 6
Extrayendo tokens
Ahora si, “tokenizamos”. Usamos la función unnest_tokens(), provista por el paquete tidytext, para realizar una operación similar a la anterior: ahora dividiremos cada línea de texto en múltiples filas dentro de nuestro dataframe, una por cada palabra. Esto hace posible analizar el texto de forma muy cómoda luego.
# A tibble: 6 x 9
link titulo ritmo ano musica compositor decada linea word
<chr> <chr> <chr> <int> <chr> <chr> <dbl> <int> <chr>
1 http://www.todota… a bail… tango 1943 domingo… homero exp… 1940 1 a
2 http://www.todota… a bail… tango 1943 domingo… homero exp… 1940 1 bail…
3 http://www.todota… a bail… tango 1943 domingo… homero exp… 1940 1 a
4 http://www.todota… a bail… tango 1943 domingo… homero exp… 1940 1 bail…
5 http://www.todota… a bail… tango 1943 domingo… homero exp… 1940 2 que
6 http://www.todota… a bail… tango 1943 domingo… homero exp… 1940 2 la
Eliminando stopwords
El siguiente paso, común a cualquier análisis de texto, es eliminar las “stopwords”. Estas son palabras muy frecuentes que no agregan significado al texto, sino que funcionan como estructura: por ejemplo “de”, “la”, “en”, “a”, etc. Al eliminarlas del texto a analizar nos aseguramos de que no aparezcan siempre entre las palabras más frecuentes encontradas, y a cambio no perdemos nada; en la práctica, las stopwords nunca son necesarias para detectar el tema de un texto.
Descargamos una lista de stopwords del lenguaje español basada en http://snowball.tartarus.org/algorithms/spanish/stop.txt
STOPWORD
1 de
2 la
3 que
4 el
5 en
6 y
Y con un “anti-join” eliminamos todas las palabras en el dataset de tangos que también aparecen en la lista. (El anti-join compara dos sets de datos en base a un campo en común, y elimina del primero todas las filas con valores que aparecen en el segundo)
Identificando las palabras más frecuentes
Habiéndonos librados de las stopwords, ya podemos hacer una lista de los términos más frecuentes en nuestra colección de letras de tango:
# A tibble: 41,290 x 2
word n
<chr> <int>
1 amor 5491
2 mas 4452
3 <NA> 4323
4 vida 3557
5 corazon 3482
6 hoy 2247
7 vos 2195
8 tango 2079
9 alma 1957
10 siempre 1941
# … with 41,280 more rows
Visualizemos la palabra más frecuente por década. Usamos slice() para “cortar” una porción de la data de cada grupo. En este caso, sólo la primera fila, que por el orden establecido en el paso anterior, es la que tiene la palabra más frecuente:
Análisis de sentimiento
Para asignar un “sentimiento” a cada palabra utilizaremos SDAL, un léxico de 2880 palabras. El SDAL fue producido por el Grupo del Procesamiento del Habla de la Facultad de Ciencias Exactas y Naturales (FCEyN), parte de la Universidad de Buenos Aires
Las palabras contenidas en el léxico han sido “puntuadas” manualmente asignando su valor según tres dimensiones afectivas:
agrado (agradable / neutra / desagradable) activación (activa / neutra / pasiva) imaginabilidad (fácil de imaginar / neutra / difícil de imaginar) Los detalles al respecto de del léxico pueden encontrarse en: Agustín Gravano & Matías Dell’ Amerlina Ríos, “Spanish DAL: A Spanish Dictionary of Affect in Language”, Reporte Técnico, Departamento de Computación, FCEyN-UBA, Febrero 2014.
Cargamos una versión adaptada del léxico:
palabra media_agrado media_activacion media_imaginabilidad
1 población -0.2 0.0 0.6
2 obra 0.2 0.4 0.4
3 dormir 1.0 -0.6 1.0
4 dar 0.8 1.0 1.0
5 realizar 0.6 1.0 0.8
6 haber 0.0 -0.2 -0.2
Cuantificando sentimiento
Vamos a comparar cuatro tangos entre sí, asignándoles una polaridad de sentimiento (de positivo a negativo) línea por línea. Nuestra guía será el valor de “agrado” para cada palabra hallada en el léxico SDAL. Un agrado alto será asociado a un sentimiento positivo, y uno bajo a sentimiento negativo.
Seleccionemos éstos clásicos:
- El día que me quieras
- Por una cabeza
- Naranjo en flor
- Garufa
Para asignar un sentimiento a cada línea de los tangos, simplemente hacemos un join con el léxico, lo cual asocia a cada palabra su valor de sentimiento. Y luego sumamos los valores para obtener el sentimiento general de cada línea:
La utilidad de analizar el sentimiento línea a línea es que podemos visualizar la progresión a medida que transcurre el tango:
El día que me quieras” alcanza sus picos de sentimiento positivo en las líneas 18 y 40. Para saber cuales son, lo consultamos con el dataset original de tangos, el que no hemos divididos letra por letra:
# A tibble: 2 x 1
letra
<chr>
1 " desde el azul del cielo"
2 " desde el azul del cielo"
De algún modo, la combinación de palabras “desde el azul del cielo” rankea muy alto de acuerdo al léxico de sentimiento que estamos usando.
“Naranjo en flor”, por su parte, muestra siempre un sentimiento positivo… excepto en los versos 24 y 25. ¿Qué contienen?
# A tibble: 2 x 1
letra
<chr>
1 " tanto dolor?"
2 " dolor de vieja arboleda"