```{r}
library(tidyverse)
library(tidytext)
```

## Introducción
Un problema muy importante en NLP es tratar de generar alguna forma de input sobre el contenido de un texto sin leerlo en su totalidad ("lectura distante"). Esto supone intentar cuantificar los contenidos de un texto. Vamos a ir viendo unas cuantas técnicas relativamente sofisticadas vinculadas al modelado de tópicos y a la constitución de embeddings de palabras más adelante, pero por ahora vamos a seguir contando palabras pero de forma más inteligente. ¿Podemos a partir del conteo de palabras llegar a tener una idea del contenido de un texto? Como vimos, una primera métrica de la importancia de una palabra es la llamada _term frequency_ ($tf$): la frecuencia con la que aparece una palabra en un documento.

Sin embargo, hay palabras en un documento que aparecen muchas veces pero que no son importantes; en castellano, probablemente palabras como "el", "es", "de", etc. Podríamos adoptar el enfoque de agregar palabras como estas a una lista de palabras vacías (stopwords) y eliminarlas antes del análisis, pero es posible que algunas de estas palabras sean más importantes en algunos documentos que en otros. Una lista de stopwords puede ser un primer paso pero no es el único ni, necesariamente, el más importante para ajustar la frecuencia de los términos para palabras de uso común.

Vamos a trabajar con dos métricas. Podemos analizar la "informatividad" de un término observando la _inverse document frequency_ ($idf$). Esta métrica disminuye el peso de las palabras de uso común y aumenta el peso de las palabras que no se usan mucho en una colección de documentos. 

Finalmente, podemos calcular la $tf-idf$ que combina ambas métricas multiplicándolas: es la frecuencia de cada término, ajustada o ponderada por la importancia que tiene en el corpus.

## Term frequency en los diarios de Renzi
Vamos a seguir con los 3 tomos de los diarios de Renzi. Examinemos primero $tf$ y luego $tf-idf$. Lo interesante de todo esto es que si nos mantenemos en nuestro formato "tidy" vamos a poder comenzar simplemente usando verbos dplyr como `group_by()` y `join()`. ¿Cuáles son las palabras más utilizadas en los diarios? (También vamos a calcular el total de palabras en cada novela aquí, para uso posterior).

```{r}
renzi <- read_csv('../data/renzi.csv') %>%
        mutate(tomo = case_when(
                tomo == '1_diarios_renzi_años_de_formacion.txt' ~ 'I-Años de formación',
                tomo == '2_diarios_renzi_los_años_felices.txt' ~ 'II-Los años felices',
                tomo == '3_diarios_renzi_un_dia_en_la_vida.txt' ~ 'III-Un día en la vida',
        ))
```

```{r}
book_words <- renzi %>%
        mutate(entry_number = row_number()) %>%
        unnest_tokens(output = word, 
                      input = entry) %>%
        group_by(tomo, word) %>%
        summarise(n = n()) %>%
        arrange(desc(n)) %>%
        ungroup()

total_words <- book_words %>% 
  group_by(tomo) %>% 
  summarize(total = sum(n))

book_words <- book_words %>%
                left_join(total_words) %>%
                ungroup() %>%
                arrange(desc(n))

book_words
```

Esta tibble `book_words` presenta una fila para cada combinación de tomo y palabras. Tiene dos columnas (además de `tomo` y `word` que ya las conocemos):

- `n` es el número de veces que se usa esa palabra en ese tomo 
- `total` es el total de palabras en ese libro. 

Vemos las palabras que eliminaríamos mediante una lista como stopwords: "de", "la", "que", etc.

En el siguiente gráfico veamos la distribución porcentual (la calculamos como `n / total`) para cada tomo, el número de veces que aparece una palabra en un tomo dividido por el número total de términos (palabras) en ese tomo. Hemos cálculado la _term frequency_ ($tf$).

```{r}
book_words %>%
        mutate(tf = n/total) %>%
        ggplot(aes(tf, fill = tomo)) +
                geom_histogram(show.legend = FALSE) +
                xlim(NA, 0.0002) +
                facet_wrap(~tomo) +
                theme_minimal()

```

Hay colas muy largas a la derecha para esos tomos (son muy raras) que no hemos mostrado en estos tramas. En general, los gráficos son similares en los tres tomos. Pocas palabras que ocurren mucho y muchas palabras que ocurrren poco.


## Calculando todas las métricas: la función `bind_tfi_idf()`
Repitámoslo una vez más: la idea de la métrica $tf-idf$ es encontrar las palabras importantes para el contenido de cada documento disminuyendo el peso de las palabras de uso común y aumentando el peso de las palabras que no se usan mucho en una colección o corpus de documentos. El cálculo de $tf-idf$ intenta encontrar las palabras que son importantes (es decir, comunes) en un texto, pero informativas (no demasiado comunes).

La función `bind_tf_idf()` en el paquete `tidytext` toma un dataset de texto tidy como entrada con una fila por token (término), por documento. Una columna (`word` en nuestro caso) contiene los términos / tokens, otra columna contiene los documentos (`tomo`, en este caso) y la última columna necesaria contiene los recuentos, cuántas veces cada documento contiene cada término (`n` en este ejemplo). Calculamos un total para cada tomo para nuestras exploraciones en las secciones anteriores, pero no es necesario para la función `bind_tf_idf ()`; la tabla solo debe contener todas las palabras de cada documento.

```{r}
book_tf_idf <- book_words %>%
  bind_tf_idf(word, tomo, n)

head(book_tf_idf)
```

Es importante notar que `idf` y, por lo tanto, `tf-idf` son cero para estas palabras extremadamente comunes (que en el ejercicio anterior, habíamos eliminado como stopwords). Todas estas son palabras que aparecen en los tres tomos de los diarios, por lo que el término `idf` (que entonces será el logaritmo natural de 1) es cero. 

La frecuencia inversa del documento (y por tanto `tf-idf`) es muy baja (cercana a cero) para las palabras que aparecen en muchos de los documentos de una colección; así es como este enfoque reduce el peso de las palabras comunes. La `idf` será un número mayor para las palabras que aparecen en una menor cantidad de documentos de la colección.

Ordenemos la tabla de forma diferente para identificar las palabras más importantes:

```{r}
book_tf_idf %>%
  select(-total) %>%
  arrange(desc(tf_idf))
```

Aquí vemos que varios nombres y apodos (carola, schucler, toto, etc.) son importantes en los tres tomos, aunque no se repiten a lo largo de los tomos.

Visualicemos estos términos. Vamos a quedarnos (para cada tomo) con los principales 20 términos según tf-idf. 

```{r}
library(forcats)

book_tf_idf %>%
  group_by(tomo) %>%
        slice_max(tf_idf, n = 20) %>%
        ungroup() %>%
        ggplot(aes(tf_idf, fct_reorder(word, tf_idf), fill = tomo)) +
        geom_col(show.legend = FALSE) +
        facet_wrap(~tomo, ncol = 2, scales = "free") +
        labs(x = "tf-idf", y = NULL) +
        theme_minimal()
```

Es muy interesante ver como los nombres aparecen pero son diferentes en cada etapa de la vida de Renzi. A su vez, en los **años de formación** se ve como la vida académica de Renzi (o sea, Piglia) tenía su importancia: términos como "concursos", "sinóptico" o "monografía" rankean entre los más imporantes. 

A medida que avanza la vida de Piglia/Renzi vemos como otros personajes como "Toto Schmucler" toma importancia en su vida y es en el segundo tomo en el que viaja a China y por eso palabras como "china" o "mao" resultan relevantes.

Finalmente, en el período final toman importancia los años "1976" y "1977", los años de encierro de la dictadura. También su migración a Estados Unidos aparece capturada por el término "princeton", la universidad en la que enseñó muchos años. Es la época en que termina de escribir y publica la novela _[Respiración Artificial]_(https://es.wikipedia.org/wiki/Respiraci%C3%B3n_artificial_(novela)) en la que "arocena" es un personaje importante (el censor y el espía que lee las cartas).

### Actividad
A partir del corpus de textos de Marx y Engels trabajado la clase pasada, identificar y graficar las 20 principales palabras en las cartas, las notas y los libros.

```{r}
###
```

## Resumen
El uso de tf-idf nos permite encontrar palabras que son características de un documento dentro de una colección de documentos, ya sea que ese documento sea una novela, un diario un texto físico o una página web. Explorar la frecuencia de los términos por sí solo puede darnos una idea de cómo se usa el lenguaje en una colección de lenguaje natural, y los verbos dplyr como `count()` y `rank()` nos brindan herramientas para razonar sobre la frecuencia de los términos. El paquete `tidytext` utiliza una implementación de tf-idf consistente con los principios de tidy data que nos permite ver cómo diferentes palabras son importantes en los documentos dentro de una colección o corpus de documentos.