freq_lemmes <- wp_flood_words %>%
group_by(lemma) %>%
summarise(freq=n()) %>%
arrange(desc(freq)) %>%
na.omit()
head(freq_lemmes)
lemma | freq |
---|---|
person | 8309 |
water | 8218 |
river | 7272 |
area | 6834 |
rain | 5952 |
damage | 5372 |
Tables lexicales, co-occurrences et corrélations, spécificités
ISIG, UMR 5600 EVS
2024-10-01
Avant de réaliser quelques graphiques pour montrer le contenu lexical de nos textes il faudra la plupart du temps quelques calculs basiques sur nos données (par exemple agréger les données pour obtenir les fréquences d’occurrence des termes).
Pour réaliser ces quelques transformations on peut généralement utiliser les fonctions de dplyr
.
Dans la suite de cet ouvrage, nous considérerons un nouveau vrai corpus de textes correspondant à l’ensemble des communiqués de presse du Ministère de la Transition écologique et de la Cohésion des territoires mis en ligne ici.
Considérons les tables suivantes, qui résultent d’un travail de récupération (par web scraping), nettoyage, tokenisation, lemmatisation de ce corpus :
Ici, on repart du tableau wp_flood_words
.
On pourrait être amené à
Le descripteur le plus basique que l’on puisse fournir concernant les lemmes est leur fréquence. On la calcule très simplement à l’aide des fonctions de dplyr
:
freq_lemmes <- wp_flood_words %>%
group_by(lemma) %>%
summarise(freq=n()) %>%
arrange(desc(freq)) %>%
na.omit()
head(freq_lemmes)
lemma | freq |
---|---|
person | 8309 |
water | 8218 |
river | 7272 |
area | 6834 |
rain | 5952 |
damage | 5372 |
Bon. La version ci-dessus est la “version longue”, faite pour remobiliser les verbes de base de dplyr
. Full disclosure: il existe une version raccourcie:
Si l’on veut caractériser les fréquences de termes non pas dans l’absolu (dans le corpus entier) mais selon une partition du corpus on peut calculer la table lexicale:
[1] 9221 285
wd:Q100293305 wd:Q10310765 wd:Q1033970
aba 0 0 0
abandon 0 0 0
abandonment 0 1 0
abate 0 0 0
abbe 0 0 0
wd:Q103821287 wd:Q10436112
aba 0 0
abandon 0 0
abandonment 0 0
abate 0 0
abbe 0 0
Ici la table lexicale porte sur l’ensemble des lemmes elle a donc pour dimension 8453 lignes (le nombre de lemme distincts) x 4 colonnes (le nombre de ministres).
La table lexicale ci-dessus permet ainsi de visualiser les effectifs croisés lemma * événement d’inondation. Cependant, pour toute analyse ultérieure de ces effectifs mieux vaut s’en tenir à une mise en forme “tidy” longue:
tib_lex_long=wp_flood_words %>%
group_by(lemma,flood,flood_label) %>%
summarise(n=n())
head(tib_lex_long)
lemma | flood | flood_label | n |
---|---|---|---|
aba | wd:Q13765056 | 2013 China flood | 4 |
aba | wd:Q96784050 | 2020 China floods | 1 |
abandon | wd:Q107596384 | 2021 Henan floods | 2 |
abandon | wd:Q108933919 | 2002 La Paz floods | 2 |
abandon | wd:Q113330937 | July 2022 United States floods | 1 |
abandon | wd:Q113482445 | 2022 Central Korean floods | 1 |
Si l’on s’intéresse non plus seulement à la fréquence individuelle des termes mais qu’on cherche à caractériser les termes qui sont souvent employés ensemble (au sein d’un même document par exemple) on peut utiliser les fonctions du package widyr
.
Considérons une paire de mots: motA
et motB
. - mot
:T (pour TRUE) correspond à l’apparition du mot - mot
:F (pour FALSE) correspond à la non-apparition du mot - \(N_{A=x,B=y}\) correspond à un effectif croisé des cas où motA
:x (T ou F) et motB
:y (T ou F)
motA :T |
motA :F |
Total | |
---|---|---|---|
motB :T |
\(N_{TT}\) | \(N_{TF}\) | \(N_{T.}\) |
motB :F |
\(N_{FT}\) | \(N_{FF}\) | \(N_{F.}\) |
Total | \(N_{.T}\) | \(N_{.F}\) | N |
La fréquence de cooccurrence d’une paire mots correspond ainsi au nombre de fois où ces deux mots apparaissent dans une même entité (ci-dessous, le “doc”). En se référant au tableau ci-dessus, il s’agirait de \(N_{TT}\)
Pour calculer les cooccurences et corrélations (un processus assez calculatoire) je vais d’abord filtrer tib_lemmes
pour ne garder que les mots ayant une fréquence d’occurrence haute…
On utilise le package widyr
pour calculer les effectifs croisés:
La corrélation, quant à elle, correspond à :
\[Cor=\frac{N_{TT}N_{FF}-N_{TF}N_{FT}}{\sqrt{N_{T.}N_{F.}N_{.F}N_{.T}}}\]
Le \(TF-IDF\) (pour “term frequency-inverse document frequency”) est une métrique qui reflète l’importance relative d’un mot dans un document.
TF{d,w} est la fréquence (ou nombre d’occurrences) du terme \(w\) dans le document \(d\). Elle mesure l’importance du terme dans le document.
IDF{d,w} est la fréquence inverse de document. Elle mesure l’importance du terme dans le corpus.
Elle se calcule comme suit, où \(D\) est le nombre total de documents et \(\{d_j: w_i \in d_j\}\) est le nombre de documents qui contiennent le terme \(w_i\): \[ IDF_{w}=log\left(\frac{D}{\{d_j: w_i \in d_j\}}\right)\]
Le \(TF-IDF\) se calcule comme le produit \(TF*IDF\). La multiplication par \(IDF\) sert notamment à minimiser la valeur de \(TF-IDF\) pour les termes les plus fréquents, qu’on suppose peu discriminants.
Le calcul du TF-IDF est proposé dans le package tidytext:
flood | lemma | n | tf | idf | tf_idf |
---|---|---|---|---|---|
wd:Q13415724 | spa | 340 | 0.1268657 | 3.349904 | 0.4249878 |
wd:Q1129089 | molasses | 373 | 0.0555804 | 5.652489 | 0.3141676 |
wd:Q3005548 | seine | 48 | 0.0341637 | 4.553877 | 0.1555773 |
wd:Q4592745 | fork | 73 | 0.0486342 | 3.167582 | 0.1540530 |
wd:Q1337934 | glacier | 191 | 0.0537725 | 2.819276 | 0.1515996 |
wd:Q4568382 | hunter | 21 | 0.0403846 | 3.455265 | 0.1395395 |
wd:Q20088998 | zoo | 109 | 0.0445990 | 3.013432 | 0.1343961 |
wd:Q4592745 | grand | 73 | 0.0486342 | 2.607967 | 0.1268365 |
wd:Q4626536 | manila | 15 | 0.0248756 | 4.959342 | 0.1233667 |
wd:Q6413525 | ash | 66 | 0.0375213 | 3.254594 | 0.1221167 |
wd:Q120690224 | underpass | 58 | 0.0396717 | 3.013432 | 0.1195479 |
wd:Q38276364 | prefecture | 28 | 0.0459770 | 2.474435 | 0.1137671 |
wd:Q37725207 | crore | 23 | 0.0421245 | 2.607967 | 0.1098594 |
wd:Q4613171 | eagle | 30 | 0.0277264 | 3.860730 | 0.1070443 |
wd:Q4942250 | snake | 32 | 0.0325203 | 3.254594 | 0.1058405 |
wd:Q117705441 | fort | 43 | 0.0410697 | 2.516995 | 0.1033723 |
wd:Q21654555 | prefecture | 27 | 0.0417311 | 2.474435 | 0.1032608 |
wd:Q6363593 | moraine | 20 | 0.0205128 | 4.959342 | 0.1017301 |
wd:Q4592748 | fork | 23 | 0.0320781 | 3.167582 | 0.1016100 |
wd:Q120669170 | advisory | 443 | 0.0378083 | 2.561447 | 0.0968440 |
wd:Q955641 | epic | 43 | 0.0223958 | 4.266195 | 0.0955450 |
wd:Q2712444 | var | 39 | 0.0209565 | 4.553877 | 0.0954332 |
wd:Q65041394 | pearl | 31 | 0.0252855 | 3.706579 | 0.0937226 |
wd:Q10436112 | myth | 32 | 0.0251969 | 3.706579 | 0.0933941 |
wd:Q36687031 | leone | 64 | 0.0187904 | 4.959342 | 0.0931879 |
wd:Q3151449 | tunnel | 58 | 0.0465490 | 1.988927 | 0.0925825 |
wd:Q1337934 | ice | 166 | 0.0467342 | 1.914820 | 0.0894876 |
wd:Q110291626 | mina | 19 | 0.0178404 | 4.959342 | 0.0884765 |
wd:Q4736086 | ice | 37 | 0.0452876 | 1.914820 | 0.0867177 |
wd:Q105105866 | debacle | 16 | 0.0152672 | 5.652489 | 0.0862975 |
Le package textometry
comprend une fonction qui permet de calculer des scores de spécificité. Le but de ce score est (comme pour le TF-IDF) d’identifier les termes spécifiques à une partie du corpus.
Le modèle probabiliste associé à cet indice est expliqué [ici] (https://txm.sourceforge.net/doc/manual/0.7.9/fr/manual59.xhtml). On peut expliquer ce modèle à travers l’image de boules et d’urnes (oui oui, comme quand on fait des probabilités au lycée…).
Considérons ainsi que les mots dans des parties d’un texte sont assimilables à des boules dans des urnes. On s’interroge quant à la spécificité d’un mot particulier -boule rose- dans une partie du corpus -urne A-, autrement dit on se demande si le nombre de boules roses dans l’urne A ci-dessous pourrait être due à une distribution au hasard ou si au contraire cette fréquence relativement élevée démontre que les boules roses sont “spécifiques” de cette urne.
Pour calculer les chances d’observer cette fréquence simplement par hasard, on utilise la loi de probabilité hypergéométrique.
Cette loi quantifie en effet la probabilité d’effectuer un tirage sans remise de \(f\) boules roses dans une urne/partie comprenant \(t\) boules en tout, en tirant dans un nombre total de boules de \(T\) boules dont \(F\) boules roses.
Dans l’exemple ci-dessus on a:
La probabilité dans ce contexte de tirer 11 boules et d’obtenir 3 boules roses ou plus est de:
On observe donc une fréquence (3) qui n’est pas complètement improbable (\(pr(X>2)\approx11\)%) sous hypothèse d’une distribution au hasard des boules. En effet, par convention, on tend à considérer un événement comme très improbable si sa probabilité est inférieure à 5% voire 1%.
Généralisation:
La spécificité se calcule ainsi comme suit:
\[Spec=-log10(pr(X \geq f))\] Elle donne donc un ordre de grandeur (ou en l’occurrence un ordre de petitesse) de la probabilité d’observer une fréquence égale ou supérieure du terme dans la partie considérée.
Autrement dit, plus la fréquence est forte et improbable sous hypothèse de distribution au hasard, plus le score est élevé, et un score \(\geq\) 2 correspond à une probabilité \(\leq\) 1%. C’est ainsi usuellement cette valeur seuil qu’on utilise pour considérer le score de spécificité comme étant significatif.
Les spécificités peuvent évidemment être calculées à la volée pour l’ensemble des termes (et non terme par terme comme on l’a fait ci-dessus à des fins pédagogiques). On utilise pour cela la fonction specificities()
du package textometry
.
Pour plus de compatibilité avec le tidyverse on peut utiliser la fonction tidy_specificities()
qui utilise la fonction du package textometry
et reformatte la sortie de cette fonction pour renvoyer un résultat tabulaire conforme à la logique “tidyverse”.