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)
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.
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:
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.
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:
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.
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
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
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.
Estas diferencias aparecen aunque más atenuadas en el caso de LDA.