library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.3     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.3     ✔ tibble    3.2.1
## ✔ lubridate 1.9.2     ✔ tidyr     1.3.0
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(stm)
## stm v1.3.6.1 successfully loaded. See ?stm for help. 
##  Papers, resources, and other materials at structuraltopicmodel.com
library(topicmodels)
library(tidytext)
library(tictoc)

Introducción

En general, una tarea que es muy frecuente en el análisis de textos es intentar dividir nuestro corpus en cierta cantidad de grupos para poder entenderlos por separado. Algo así como hacer una primera lectura de nuestro corpus sin tener que leer los documentos uno por uno. Las técnicas de modelado de tópicos son una gran aliada para este tipo de taras.

En este notebook vamos a introducir una técnica para efecutar esta tarea que se diferencia de Latent Dirichlet Allocation (LDA) en varios aspectos.

Structural Topic Modeling (STM). Analizando revistas para mujeres y para hombres

STM provee un marco general para el modelado de tópicos pero su característica fundamental es que permite incorporar información de covariables a nivel de documento.

Este punto es sumamente importante porque permite flexibilizar uno de los supuestos más fuertes de LDA: que los tópicos son constantes para todo el corpus. STM permite incorporar la influencia de ciertas covariables sobre los tópicos en dos aspectos:

  • la prevalencia de los tópicos (el peso de cada tópico en cada documento)
  • el contenido de los tópicos (la probabilidad de cada palabra de aparecer en el corpus)

Estas covariables pueden mejorar la inferencia y la interpretabilidad de los temas detectados.

En estos links pueden encontrar algunos papers que detallan algunos de los supuestos y métodos de estimación de STM

Y aquí el sitio del paquete implmenetado en R.

Si bien no nos vamos a meter en detalle en la matemática del modelo diremos que en STM se reemplazan las distribuciones de probabilidad que se usan en LDA por modelos lineales generalizados para poder correlacionar las covariables con la distribución de tópicos por documentos y de palabras por tópico.

Veamos un ejemplo con el mismo corpus que utilizamos la semana pasada:

revistas <- read_csv('../data/revistas_limpias_final.csv')
## Rows: 3980 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (4): categoria, fecha, titulo, text
## dbl (1): id
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(revistas)
## # A tibble: 6 × 5
##      id categoria fecha                     titulo                         text 
##   <dbl> <chr>     <chr>                     <chr>                          <chr>
## 1     1 Hombre    4  de marzo de 2018       Los ex caddies que se organiz… "Nin…
## 2     2 Hombre    2  de marzo de 2018       El documental sobre la gran e… "Del…
## 3     3 Hombre    15  de febrero de 2018    Porfolio fotográfico: Guiller… "Las…
## 4     4 Hombre    3  de diciembre de 2017   Pipi Piazzolla, el músico que… "\n\…
## 5     5 Hombre    29  de marzo de 2016      Perfil Geek: hoy Ezequiel Cal… "\nC…
## 6     6 Hombre    28  de marzo de 2016      3 shows imperdibles en Buenos… "\n\…

Vamos a normalizar, primero, los campos de texto. Con esta instrucción cambiamos el encoding de texto de los campos text y title y lo pasamos a ASCII. Esta es una forma bastante rápida de eliminar tildes, ñ y otros acentos.

revistas <- revistas %>%
                mutate(text = stringi::stri_trans_general(text, "Latin-ASCII"),
                       titulo = stringi::stri_trans_general(titulo, "Latin-ASCII"))

Eliminamos los dígitos que encontremos en el texto…

revistas <- revistas %>%
          mutate(text = str_replace_all(text, '[[:digit:]]+', ''))

Ahora podemos tokenizarlo:

revistas_tidy <- revistas %>%
                unnest_tokens(word, text)
stop_words <- read_delim('../data/stopwords.txt', 
                         delim = '\t',
                         col_names = c('word')) %>%
                        mutate(word=stringi::stri_trans_general(word, "Latin-ASCII"))
## Rows: 732 Columns: 1
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: "\t"
## chr (1): word
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## Aquí agregamos algunas palabras al listado de stopwords...
stop_words <- stop_words %>%
                bind_rows( tibble(word=c('ano', 'anos', 'ohlala', 'foto', 'the'))) 
revistas_tidy <- revistas_tidy %>%
                anti_join(stop_words)
## Joining with `by = join_by(word)`
metadata <- revistas_tidy %>%
                  select(id, categoria) %>%
                  distinct() %>%
                  left_join(revistas %>% select(id, text))
## Joining with `by = join_by(id)`

Primero, generamos nuestra tabla tidy de conteos

word_counts <- revistas_tidy %>%
        group_by(id, word) %>%
        summarise(n=n()) %>%
        ungroup()
## `summarise()` has grouped output by 'id'. You can override using the `.groups`
## argument.

Modelado de tópicos: STM

Para hacer el modelado de temas como se implementa aquí, necesitamos generar una DocumentFrequencyMatrix, un tipo especial de matriz del paquete quanteda (por supuesto, esto es solo una implementación específica del concepto general de una TFM).

Tenemos hasta aquí nuestra estructura de datos habitual: un token por fila y una columna de conteo. Vamos a transformarla ahora a una DFM del paquete :

revistas_dfm <- word_counts %>%
                cast_dfm(id, word, n)

revistas_dfm
## Document-feature matrix of: 3,930 documents, 111,484 features (99.80% sparse) and 0 docvars.
##     features
## docs aag abajo abandonarlo abierto abiertos abre abrian aca aceptaran
##    1   2     2           1       1        1    1      1   5         1
##    2   0     0           0       0        0    0      0   0         0
##    3   0     0           0       0        0    0      0   0         0
##    4   0     0           0       0        0    0      0   0         0
##    5   0     0           0       0        0    0      0   0         0
##    6   0     0           0       0        0    0      0   0         0
##     features
## docs acumulacion
##    1           1
##    2           0
##    3           0
##    4           0
##    5           0
##    6           0
## [ reached max_ndoc ... 3,924 more documents, reached max_nfeat ... 111,474 more features ]
# 
# stm_15 <- stm(documents = revistas_dfm,
#      K = 15,
#      prevalence = ~categoria,
#      max.em.its = 75, 
#      data = metadata,
#      init.type = "Spectral")
# write_rds(stm_15, '../models/stm_15_prev_cont.rds')
#

stm_15 <- read_rds('../models/stm_15_prev.rds')

Generamos las dos matrices fundamentales: la de palabras x tópico y la documentos x tópico

betas_stm <- tidy(stm_15, matrix='beta')
doc_2_topics_stm <- tidy(stm_15, matrix='theta')

Primero, veamos las matrices de palabras por topicos.

 betas_stm %>%
  group_by(topic) %>%
  slice_max(beta, n = 15) %>% 
  ungroup() %>%
  arrange(topic, -beta) %>%
  mutate(term = reorder_within(term, beta, topic)) %>%
  ggplot(aes(beta, term, fill = factor(topic))) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~ topic, scales='free_y') +
  scale_y_reordered() +
  theme_minimal()

En el caso de STM podemos ver los siguientes tópicos:

  1. Entretenimientos/espectáculos
  2. Misc.
  3. Moda, look
  4. Moda, diseño
  5. Pareja
  6. Deportes
  7. Espectáculos/series
  8. Música y discos
  9. Autos (tecnología? economía?)
  10. Música y cocina (salidas, quizás…)
  11. Vinos
  12. Cuidado del pelo
  13. Cocina y restaurantes
  14. Alimentación, cuidado del cuerpo
  15. Niños y educación

Algunas herramientas de validación de STM

Ahora bien, una vez que hemos estimado nuestro modelo de tópicos STM es sumamente importante proceder a la validación del mismo. Vamos a ver que el paquete stm tiene implementadas algunas funciones que hacen bastante fácil esta tarea de validación.

Vamos a ver dos posibles formas de avanzar en una validación del modelo. La primera, es analizar las palabras que forman parte de cada tópico. Es decir, lo que hemos venido haciendo. Pero con una diferencia: hasta aquí habíamos trabajado con las palabras que tienen mayor \(\beta\) es decir, mayor probabilidad de pertenecer a cada tópico. STM nos permite obtener otros listados de palabras. Llamemos a la siguiente función:

labelTopics(stm_15)
## Topic 1 Top Words:
##       Highest Prob: historia, libro, cine, pelicula, vida, mundo, libros 
##       FREX: puccio, herzog, aira, patan, saxer, vallee, fitzcarraldo 
##       Lift: aamec, abalanzarse, abarcarlo, abbiamo, abducido, abejascaja, abnegado 
##       Score: patan, puccio, aira, herzog, ragendorfer, puel, mapuches 
## Topic 2 Top Words:
##       Highest Prob: vida, mundo, amor, casa, iba, gente, amigos 
##       FREX: cari, aprendi, pude, pense, llorar, camilo, aventuras 
##       Lift: abandonemos, abatido, abayuba, abduccion, abdujo, abonan.coco, abordan.ficciones 
##       Score: cari, abayuba, atrevi, planetarios, iba, pichu, aventuras 
## Topic 3 Top Words:
##       Highest Prob: look, prendas, vestido, moda, looks, estilo, gentileza 
##       FREX: blusa, mileinstagram, ohlaleando, besossofi, malter, trademark, chatitas 
##       Lift: _asi, _blanco, _cruzo, _en, _jeanettemadsen_, _jeanettemadsen_yuwei, _ni 
##       Score: guada, looks, malter, falda, sandalias, prendas, blusa 
## Topic 4 Top Words:
##       Highest Prob: color, piel, colores, moda, estilo, diseno, produccion 
##       FREX: eau, lip, fragancia, pestanas, rovedaque, labios, fragancias 
##       Lift: abotinado, addict, afrutada, annoni, antifatiga, apilable, asos 
##       Score: beauty, rovedaque, cejas, fragancia, hidratante, labial, fps 
## Topic 5 Top Words:
##       Highest Prob: vos, pareja, vida, amor, vas, cuerpo, tomar 
##       FREX: mescon, planetas, parto, menstruacion, partos, lactancia, ejercicios 
##       Lift: aaarbaentrenamiento, abalanzamos, abandonaremos, abandonarte, abarque, abdomenes, abierta.tu 
##       Score: mescon, parto, planetas, obstetra, aliadocon, lactancia, pluton 
## Topic 6 Top Words:
##       Highest Prob: futbol, club, equipo, vida, argentina, partido, mundo 
##       FREX: afa, baigorri, fifa, nadal, arquero, gorbea, corbatta 
##       Lift: arquero, gorbea, nadal, a.n.i.m.a.l, aafg, abdicacion, abdo 
##       Score: baigorri, afa, corbatta, tunante, fifa, gabelli, river 
## Topic 7 Top Words:
##       Highest Prob: produccion, vida, serie, mujeres, casa, historia, mundo 
##       FREX: tanoira, guajardo, yamila, ines, engel, porno, lectoure 
##       Lift: abstenia, abstract, acm, akinnagbe, alcoholera, amchitka, anorexica 
##       Score: tanoira, guajardo, yamila, tale, handmaid's, engel, lectoure 
## Topic 8 Top Words:
##       Highest Prob: musica, by, on, instagram, mundo, and, disco 
##       FREX: shared, oct, celestebarber, pdt, friends, at, photo 
##       Lift: acerbi, alexisren, allthatisthreeuna, always, anastasia, anyone, arozona 
##       Score: shared, at, celestebarber, oct, cannabis, album, pm 
## Topic 9 Top Words:
##       Highest Prob: sistema, mundo, mercado, argentina, tecnologia, empresa, modelo 
##       FREX: nm, torque, usb, llantas, suv, hardware, abs 
##       Lift: aa, aaa, aac, aade, aapresid, aaro, aasbo 
##       Score: pulgadas, torque, nm, llantas, suv, cv, gb 
## Topic 10 Top Words:
##       Highest Prob: musica, cocina, argentina, vino, aires, mundo, vinos 
##       FREX: whiskies, cabrales, maltas, cocteleria, bordenave, cheval, miscelanea 
##       Lift: barraza, derviches, discosopas, ezquiaga, iaies, jacqui, salitre 
##       Score: cocineros, vinos, cocteleria, gastronomia, chef, restaurante, gin 
## Topic 11 Top Words:
##       Highest Prob: vino, vinos, uvas, elaborado, meses, aromas, acidez 
##       FREX: varietal, agrelo, gualtallary, tipicidad, tril, barricas, enologo 
##       Lift: espinacito, beberlo, varietal, abasto.de, abdalainstagram, abdicar, abductor 
##       Score: uvas, taninos, enologo, roble, vinos, malbec, cabernet 
## Topic 12 Top Words:
##       Highest Prob: pelo, mujeres, cabello, vida, mundo, mujer, tipo 
##       FREX: kamatsu, peinado, elvive, puntas, rizos, pelo, rulos 
##       Lift: aaaarw, aag, aat, abandonaba.y, abandonado.para, abandonaste, abdellatif 
##       Score: kamatsu, elvive, cabello, sexadores, luneros, hajj, shampoo 
## Topic 13 Top Words:
##       Highest Prob: cocina, ciudad, platos, cafe, podes, restaurante, barrio 
##       FREX: menu, sandwiches, bircz, pasteleria, brunch, postre, platos 
##       Lift: abbesses, abisko, aboitiz, aceros, acertijos, ache, aeroclub 
##       Score: menu, restaurante, langostinos, chef, sandwiches, sabores, salsa 
## Topic 14 Top Words:
##       Highest Prob: agua, piel, alimentos, azucar, leche, aceite, alimentacion 
##       FREX: cucharadita, bol, grasas, cucharadas, sebo, nutrientes, grasa 
##       Lift: acesulfame, agave, agregales, alcalino, alergicos, amapola, antiinflamatorias 
##       Score: grasas, calorias, grasa, ml, azucar, aceite, harina 
## Topic 15 Top Words:
##       Highest Prob: chicos, argentina, aires, personas, taller, proyecto, ciudad 
##       FREX: taller, docentes, escuelas, especies, fundacion, educativo, aves 
##       Lift: a.a.e.e.h, abandonos, abdul, abete, abis, abogada.el, abogadas 
##       Score: sillerico, innocence, aves, nisman, nievas, educativo, especies

Esta salida nos muestra cuatro listados de palabras. Vamos a centrarnos en las dos primeras.

  • Highest prob: son las palabras dentro de cada tema con la mayor probabilidad (deducidas directamente del parámetro de distribución tema-palabra \(\beta\)). Son las que usamos en los plots de más arriba.

  • FREX: es una métrica que intenta combinar la frecuencia (\(\beta\)) con la exclusividad. Es decir, las palabras con alta FREX son palabras que distinguen temas: es decir, son frecuentes y exclusivas. Esto se calcula tomando la media armónica del rango por probabilidad dentro del tópico (frecuencia, es decir, el parámetro \(\beta\)) y la exclusividad es una medida que trata de cuantificar el uso relativo de un término en un tópico en relación al uso que se le da en otros tópicos.

Fijémonos el tópico 9:

Topic 9 Top Words:
     Highest Prob: sistema, mundo, mercado, argentina, tecnologia, empresa, modelo 
     FREX: nm, torque, usb, llantas, suv, hardware, abs 
     Lift: aa, aaa, aac, aade, aapresid, aaro, aasbo 
     Score: pulgadas, torque, nm, llantas, suv, cv, gb 

Si vemos las palabras de alto \(\beta\) pareciera que habla de economía o algo así. Pero si vemos las de FREX aparecen temas vinculados a autos. Un paso siguiente para validar este tópico sería tratar de leer documentos con alta frecuencia de este tópico.

Para examinar documentos que están altamente asociados con temas, la función findThoughts() puede ser usada. Esta función imprimirá los documentos altamente asociados con cada tema. Leer estos documentos es útil para comprender el contenido de un tema e interpretar su definicion.

findThoughts(stm_15, 
             texts=metadata %>% mutate(text = str_sub(text, 1, 200)) %>% select(text) %>% pull(), 
             n=10, 
             topics=9)
## 
##  Topic 9: 
##       
## En el mundo de los fabricantes de autos, el valor simbolico de la insignia es, a veces, el mayor capital del grupo empresario que la comercializa, y por eso son cuestionables las campanas de difusion
##      En la primera mitad de , el gobierno nacional anuncio con bombos y platillos la baja de aranceles para la importacion de vehiculos electricos, hibridos y de propulsion a hidrogeno. La noticia genero e
##      
## 
## Los  formaron parte de una decada inolvidable para los amantes de los fierros, especialmente por la aparicion de los hatchbacks picantes, versiones deportivas de coches populares, un concepto que h
##      
## Fue a principios de los  cuando la industria japonesa se propuso conquistar los mercados del mundo. Entonces lanzo uno de sus principales representantes, concebido como un vehiculo economico y popula
##      
## 
## La quinta generacion del Ford Mondeo se vendia en nuestro pais desde , pero el ultimo restyling del buque insignia de la marca de Detroit trae suficientes cambios como para anunciarse con todo. Son
##      
## A finales del ano pasado, Ford anuncio la renovacion de su gama mas alta y la llegada durante  de las nuevas versiones del Mondeo, el C-Max y la Kuga. Desde su llegada al pais hace seis anos, la Kuga
##      
## Los autos hibridos circulan por los caminos del mundo hace una decada. Y los electricos estan empezando a ganar terreno en los mercados centrales. Casi a diario escuchamos una nueva de Elon Musk, el 
##      
## 
## 
## Desde su aparicion hace seis anos, la Volkswagen Amarok se gano un lugar merecido en el pais de las pick-ups. Con fama de ser la mas comoda, su andar de auto y sus prestaciones de confort marcaro
##      
## Pocos autos sacudieron tanto el tablero. Cuando llego el Ford Ka, en , todos hablaban de el. Que era un auto para mujeres, decian los muchachos. Y las mujeres coincidian: era simpatico, facil de mane
##      
## La octava edicion del Salon Internacional de Buenos Aires sacudio la agenda del sector y las marcas concentraron buena parte de sus lanzamientos del ano en esta muestra que, en pleno auge de venta de

Al ver los primeros 10 documentos parece claro que se trata de tópico que habla de autos, sobre todo.

Actividad

Repetir el ejercicio de validación con el tópico 5. ¿Qué pueden decir al respecto?

labelTopics(stm_15, topic=5)
## Topic 5 Top Words:
##       Highest Prob: vos, pareja, vida, amor, vas, cuerpo, tomar 
##       FREX: mescon, planetas, parto, menstruacion, partos, lactancia, ejercicios 
##       Lift: aaarbaentrenamiento, abalanzamos, abandonaremos, abandonarte, abarque, abdomenes, abierta.tu 
##       Score: mescon, parto, planetas, obstetra, aliadocon, lactancia, pluton
findThoughts(stm_15, 
             texts=metadata %>% mutate(text = str_sub(text, 1, 200)) %>% select(text) %>% pull(), 
             n=10, 
             topics=5)
## 
##  Topic 5: 
##       Foto: OHLALA! 
##           Mucha energia sutil este mes envolviendo el planeta. Nos va a atravesar hasta lo mas ajeno, como si nos pasara a nosotras. Con el Sol en Acuario, con la Luna en Piscis y con 
##      Foto: OHLALA! 
##           Mucha energia sutil este mes envolviendo el planeta. Nos va a atravesar hasta lo mas ajeno, como si nos pasara a nosotras. Con el Sol en Acuario, con la Luna en Piscis y con 
##      Vamos a tener que aprender a mediar velocidades extremas. Por un lado, tres planetas en el signo Tauro nos van a llevar a buscar lo conveniente, lo seguro, lo tangible, lo que podemos saborear serenam
##      Vamos a poder alcanzar logros  que venian postergados y a estar cargadas de confianza y optimismo, expresando a fondo nuestros talentos y lo mas genuino de nuestra individualidad. Solo vamos a tener q
##      Foto: PixabayCon la Luna en Capricornio y con Saturno alejandose de Sagitario, pero aun ahi, con su presencia que se hace mas intensa por estar en los ultimos grados del signo; vamos a estar coordinan
##      Tres planetas dentro de la franja zodiacal escorpiana van a movilizar al planeta entero, que va a estar haciendo acrobacia con la sombra. Lo mas oscuro de todo y de todos va a estallar para que nada q
##      Foto: LatinstockLos radares ultrasonicos multidimensionales de la Luna en Acuario nos van a meter en la ola infinita del ahora y vamos a lograr integrar a esta realidad capricorniana una vibracion mas
##      La paciencia no va a ser el punto fuerte de nadie este mes, con Marte, Urano y Venus en Aries. Vamos a ir directamente al grano de cada situacion, sin vacilaciones, y el aire va a estar cargado de chi
##      Con la Luna en Escorpio, van a estar aflorando de tu intimidad esas emociones cuidadosamente controladas: las mas desagradables y las mas potentes. No dejes que tus miedos le ganen a este proceso en e
##      Junio nos va a encontrar repartidas entre varios intereses, compartiendo experiencias, livianas de equipaje, curiosas y entusiastas.Y como no podia ser de otra manera y para dar constancia de la gener

Comparando con un modelo LDA

Vamos a entrenar un LDA de 15 tópicos. La idea es tenerlo como “benchmark” para comparar los resultados con los que van a salir de STM.

Generamos la DTM:

revistas_dtm <- word_counts %>% 
                  cast_dtm(id, word, n)

revistas_dtm
## <<DocumentTermMatrix (documents: 3930, terms: 111484)>>
## Non-/sparse entries: 889157/437242963
## Sparsity           : 100%
## Maximal term length: NA
## Weighting          : term frequency (tf)

Entrenamos el LDA (en realidad, lo tenemos pre-entrenado)

#lda_15 <- LDA(revistas_dtm, k=15, control = list(seed = 9514))
lda_15 <- read_rds('../models/lda_15.rds')

Generamos las matrices de betas y gammas:

betas_lda <- tidy(lda_15, matrix='beta')
doc_2_topics_lda <- tidy(lda_15, matrix='gamma')

Y veamos las palabras más relevantes en cada tópico de lDA

 betas_lda %>%
  group_by(topic) %>%
  slice_max(beta, n = 15) %>% 
  ungroup() %>%
  arrange(topic, -beta) %>%
  mutate(term = reorder_within(term, beta, topic)) %>%
  ggplot(aes(beta, term, fill = factor(topic))) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~ topic, scales='free_y') +
  scale_y_reordered() +
  theme_minimal() +
  theme(text = element_text(size = 5))

Podemos etiquetar de alguna forma estos tópicos

  1. Misc.
  2. Entretenimiento general (libros, películas, series, TV)
  3. Alimentación y salud (con otras palabras raras)
  4. Pareja y cuerpo
  5. Músca
  6. Cuidado del cuerpo
  7. Cocina
  8. Misc.
  9. Moda (ropa, zapatos, etc.)
  10. Deportes
  11. Entretenimiento (TV, series)
  12. Tecnología/autos (?)
  13. Economía/tecnología
  14. Vinos
  15. Cocina y gastronomía
Tópico nro. STM LDA
1 Entretenimientos/espectáculos Misc.
2 Misc. Entretenimiento general (libros, películas, series, TV)
3 Moda, look Alimentación y salud (con otras palabras raras)
4 Moda, diseño Pareja y cuerpo
5 Horóscopo Músca
6 Deportes Cuidado del cuerpo
7 Espectáculos/series Cocina
8 Música y discos Misc.
9 Autos (tecnología? economía?) Moda (ropa, zapatos, etc.)
10 Música y cocina (salidas, quizás…) Deportes
11 Vinos Entretenimiento (TV, series)
12 Cuidado del pelo Tecnología/autos (?)
13 Cocina y restaurantes Economía/tecnología
14 Alimentación, cuidado del cuerpo Vinos
15 Niños y educación Cocina y gastronomía

Vemos cómo hay algunos tópicos que aparecen en ambos modelos: vinos, entretenimiento, cocina y gastronomía. No obstante, STM pareciera ser un poco más específico. Hay menos tópicos no interpretables y a su vez, pareciera haber menos mezclas en los tópicos.

Por ejemplo, en LDA vemos que el tópico 4 parece hablar de dos cosas diferentes: pareja y cuidado del cuerpo. En cambio, estos dos temas aparecen separados como dos tópicos diferenciados en STM.

A su vez, en LDA vemos que hay un tópico que habla de “entretenimiento en general”. En cambio, hay 3 tópicos al respecto en STM y con temas bien delimitados.

Por último, veamos cómo se distribuye la prevalencia de cada tópico según nuestra variable de corte:

doc_2_topics_stm <- doc_2_topics_stm %>%
  rename(id=document) %>%
  left_join(metadata)
## Joining with `by = join_by(id)`
doc_2_topics_stm %>%
  group_by(categoria, topic) %>%
  summarise(mean = mean(gamma)) %>%
  drop_na() %>%
  ggplot(aes(x=categoria, y=mean, fill=categoria)) + 
    geom_col(position='dodge') +
    facet_wrap(~topic) +
    theme_minimal()
## `summarise()` has grouped output by 'categoria'. You can override using the
## `.groups` argument.

doc_2_topics_lda <- doc_2_topics_lda %>%
  rename(id=document) %>%
  mutate(id=as.integer(id)) %>%
  left_join(metadata)
## Joining with `by = join_by(id)`
doc_2_topics_lda %>%
  group_by(categoria, topic) %>%
  summarise(mean = mean(gamma)) %>%
  drop_na() %>%
  ggplot(aes(x=categoria, y=mean, fill=categoria)) + 
    geom_col(position='dodge') +
    facet_wrap(~topic) +
    theme_minimal()
## `summarise()` has grouped output by 'categoria'. You can override using the
## `.groups` argument.

Pareciera que se observan diferencias más marcadas en el modelo STM. Lo cual era esperable, en tanto era el objetivo de introducir covariables.

  • los tópicos 3, 4 y 5 son predominantemente femeninos y con diferencias fuertes: entre unos 8 y 15 puntos porcentuales.
  • los tópicos 1, 6, 9 y 10 son, en cambio, predominantemente masculinos.

Estas diferencias aparecen aunque más atenuadas en el caso de LDA.