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"