Chapitre 4 Langage naturel

tibtot_commentaires <- readr::read_csv("data/tibtot_commentaires.csv")
tibtot_commentaires
## # A tibble: 12 x 3
##    doc             texte                             auteur               
##    <chr>           <chr>                             <chr>                
##  1 data/blog_de_g~ Et pour une poule sur un mur qui~ Emma, 22 ans, Limoges
##  2 data/blog_de_g~ Je vois que vous êtes, telle la ~ Michel, 56 ans, Renn~
##  3 data/blog_de_j~ Les thons, avec un t comme croco~ Eddie, 76 ans, Saint~
##  4 data/blog_de_j~ Pourquoi ces thons ne préféraien~ Yves, 40 ans, Lyon   
##  5 data/blog_de_j~ Tout ça me fait penser au blog d~ Roberta, 18 ans, Col~
##  6 data/blog_de_j~ Je préfère la chanson qui parle ~ Eduardo, 29 ans, Fer~
##  7 data/blog_de_j~ On ne comprend pas trop cette pa~ Lise, 35 ans, Lyon   
##  8 data/blog_de_j~ Et pendant ce temps-là, le roi d~ Nadia, 43 ans, Lisie~
##  9 data/blog_de_n~ A quel moment faut-il claquer du~ Jonas, 37 ans, Stras~
## 10 data/blog_de_n~ Norbert, mon petit chat, ça fait~ Julie, 34 ans, Saint~
## 11 data/blog_de_n~ L'ambiance doit être sympa quand~ Mickaël, 23 ans, Glos
## 12 data/blog_de_n~ Vous devez avoir un grain pour é~ Viviane, 58 ans, Ser~

4.1 Tokenization

On va maintenant passer à l’étape de tokenisation de nos textes.

Tokeniser, ça revient à définir de quelle manière on découpe nos textes pour les analyses ultérieures.

Par exemple, on peut décider que l’unité d’analyse (l’individu) pour nos analyses textuelles seront un des éléments suivants:

  • la phrase
  • le n-gram
  • le mot
  • etc.

Pour réaliser cette tokenisation nous allons utiliser le package tidytext et notamment sa fonction unnest_tokens().

tibtot_commentaires %>% 
  tidytext::unnest_tokens(output="bigramme",
                          input=texte,
                          token="ngrams",
                          n=2)
## # A tibble: 207 x 3
##    doc                      auteur                bigramme      
##    <chr>                    <chr>                 <chr>         
##  1 data/blog_de_ginette.htm Emma, 22 ans, Limoges et pour       
##  2 data/blog_de_ginette.htm Emma, 22 ans, Limoges pour une      
##  3 data/blog_de_ginette.htm Emma, 22 ans, Limoges une poule     
##  4 data/blog_de_ginette.htm Emma, 22 ans, Limoges poule sur     
##  5 data/blog_de_ginette.htm Emma, 22 ans, Limoges sur un        
##  6 data/blog_de_ginette.htm Emma, 22 ans, Limoges un mur        
##  7 data/blog_de_ginette.htm Emma, 22 ans, Limoges mur qui       
##  8 data/blog_de_ginette.htm Emma, 22 ans, Limoges qui picoterait
##  9 data/blog_de_ginette.htm Emma, 22 ans, Limoges picoterait du 
## 10 data/blog_de_ginette.htm Emma, 22 ans, Limoges du pain       
## # ... with 197 more rows
tib_mots=tibtot_commentaires %>% 
  tidytext::unnest_tokens(output="mot",
                          input=texte,
                          token="words")
tib_mots
## # A tibble: 219 x 3
##    doc                      auteur                mot       
##    <chr>                    <chr>                 <chr>     
##  1 data/blog_de_ginette.htm Emma, 22 ans, Limoges et        
##  2 data/blog_de_ginette.htm Emma, 22 ans, Limoges pour      
##  3 data/blog_de_ginette.htm Emma, 22 ans, Limoges une       
##  4 data/blog_de_ginette.htm Emma, 22 ans, Limoges poule     
##  5 data/blog_de_ginette.htm Emma, 22 ans, Limoges sur       
##  6 data/blog_de_ginette.htm Emma, 22 ans, Limoges un        
##  7 data/blog_de_ginette.htm Emma, 22 ans, Limoges mur       
##  8 data/blog_de_ginette.htm Emma, 22 ans, Limoges qui       
##  9 data/blog_de_ginette.htm Emma, 22 ans, Limoges picoterait
## 10 data/blog_de_ginette.htm Emma, 22 ans, Limoges du        
## # ... with 209 more rows

4.2 Nettoyage de la table

  • retirer les mots vides
  • extraire la racine des mots ou le lemme (stemming, lemmatisation)
  • retirer la ponctuation
  • retirer certains mots ou expressions
  • changer la casse (passer majuscules en minuscules)
  • retirer les liens, les “hashtags”, les emojis, etc.
  • etc.

4.2.1 Nettoyage de la table par suppression des mots vides

Pour des textes en anglais, tidytext comprend une liste de mots vides (“stopwords”)

tidytext::stop_words
## # A tibble: 1,149 x 2
##    word        lexicon
##    <chr>       <chr>  
##  1 a           SMART  
##  2 a's         SMART  
##  3 able        SMART  
##  4 about       SMART  
##  5 above       SMART  
##  6 according   SMART  
##  7 accordingly SMART  
##  8 across      SMART  
##  9 actually    SMART  
## 10 after       SMART  
## # ... with 1,139 more rows

Pour un texte en français, on peut avoir recours au package proustr lien ici

proustr::proust_stopwords()
## # A tibble: 783 x 1
##    word      
##  * <fct>     
##  1 a         
##  2 abord     
##  3 absolument
##  4 afin      
##  5 ah        
##  6 ai        
##  7 aie       
##  8 aient     
##  9 aies      
## 10 ailleurs  
## # ... with 773 more rows

Pour ne garder que les mots signifiants, on peut ainsi faire une anti-jointure entre notre table et la table renvoyée par proust_stopwords():

tib_mots_nonvides <- tib_mots %>%
  anti_join(proustr::proust_stopwords(),by=c("mot"="word"))
tib_mots_nonvides
## # A tibble: 88 x 3
##    doc                      auteur                mot       
##    <chr>                    <chr>                 <chr>     
##  1 data/blog_de_ginette.htm Emma, 22 ans, Limoges poule     
##  2 data/blog_de_ginette.htm Emma, 22 ans, Limoges mur       
##  3 data/blog_de_ginette.htm Emma, 22 ans, Limoges picoterait
##  4 data/blog_de_ginette.htm Emma, 22 ans, Limoges pain      
##  5 data/blog_de_ginette.htm Emma, 22 ans, Limoges dur       
##  6 data/blog_de_ginette.htm Emma, 22 ans, Limoges c'est     
##  7 data/blog_de_ginette.htm Emma, 22 ans, Limoges nourrir   
##  8 data/blog_de_ginette.htm Emma, 22 ans, Limoges petits    
##  9 data/blog_de_ginette.htm Emma, 22 ans, Limoges cochons   
## 10 data/blog_de_ginette.htm Emma, 22 ans, Limoges qu'en     
## # ... with 78 more rows

4.2.2 Nettoyage de la table par racinisation (stemming)

La racinisation (ou désuffixation, ou stemming en anglais) consiste (comme son nom l’indique) à extraire la racine d’un mot. Souvent, cette racine ne correspond pas à un “vrai mot”…

proustr::pr_stem_words(tib_mots_nonvides,mot)
## # A tibble: 88 x 3
##    doc                      auteur                mot   
##  * <chr>                    <chr>                 <chr> 
##  1 data/blog_de_ginette.htm Emma, 22 ans, Limoges poul  
##  2 data/blog_de_ginette.htm Emma, 22 ans, Limoges mur   
##  3 data/blog_de_ginette.htm Emma, 22 ans, Limoges picot 
##  4 data/blog_de_ginette.htm Emma, 22 ans, Limoges pain  
##  5 data/blog_de_ginette.htm Emma, 22 ans, Limoges dur   
##  6 data/blog_de_ginette.htm Emma, 22 ans, Limoges c'est 
##  7 data/blog_de_ginette.htm Emma, 22 ans, Limoges nourr 
##  8 data/blog_de_ginette.htm Emma, 22 ans, Limoges petit 
##  9 data/blog_de_ginette.htm Emma, 22 ans, Limoges cochon
## 10 data/blog_de_ginette.htm Emma, 22 ans, Limoges qu'en 
## # ... with 78 more rows

4.2.3 Nettoyage de la table par lemmatisation

La lemmatisation consiste faire correspondre à un mot (ou forme) la forme neutre (ou lemme) que ce mot aurait par exemple par défaut dans un dictionnaire.

Il est possible de lemmatiser en utilisant l’outil TreeTagger (gratuit, mais propriétaire). Cet outil est utilisable dans R via le package koRpus vignette ici

Pour ma part, je lemmatise la plupart du temps en me basant sur une base de données lexicales libre, Lexique qui fait correspondre formes et lemmes de très nombreux mots en français. J’ai réalisé une simple jointure, sans considération syntaxique.

lexique382=mixr::get_lexicon("fr")
dplyr::sample_n(lexique382,10)
## # A tibble: 10 x 3
##    word            lemma           type 
##    <chr>           <chr>           <chr>
##  1 mérou           mérou           nom  
##  2 éboueurs        éboueur         nom  
##  3 affligeant      affligeant      adj  
##  4 participais     participer      ver  
##  5 anti_dramatique anti_dramatique adj  
##  6 rouillures      rouillure       nom  
##  7 dispenseras     dispenser       ver  
##  8 ensauvageait    ensauvager      ver  
##  9 empennée        empenner        ver  
## 10 casse_gueule    casse_gueule    nom

Dans ce cas on réalise une jointure pour récupérer le lemme de chaque mot dans notre table:

tib_mots_nonvides <- dplyr::left_join(tib_mots_nonvides,
                                      lexique382,
                                      by=c("mot"="word"))
tib_mots_nonvides %>% 
  dplyr::select(mot,lemma)
## # A tibble: 88 x 2
##    mot        lemma  
##    <chr>      <chr>  
##  1 poule      poule  
##  2 mur        mur    
##  3 picoterait <NA>   
##  4 pain       pain   
##  5 dur        dur    
##  6 c'est      <NA>   
##  7 nourrir    nourrir
##  8 petits     petit  
##  9 cochons    cochon 
## 10 qu'en      <NA>   
## # ... with 78 more rows

4.3 Correspondance mot-sentiment

proustr::proust_sentiments() %>% 
  head(n=10)
## # A tibble: 10 x 2
##    word            polarity
##    <chr>           <chr>   
##  1 à ce endroit là positive
##  2 à le hâte       negative
##  3 à part          negative
##  4 à pic           negative
##  5 à rallonge      negative
##  6 abasourdir      negative
##  7 ablation        negative
##  8 abominable      negative
##  9 abrupt          negative
## 10 absent          negative
proustr::proust_sentiments(type="score") %>% 
  head(n=10)
## # A tibble: 10 x 2
##    word        sentiment
##    <chr>       <chr>    
##  1 abaissement sadness  
##  2 abaisser    sadness  
##  3 abandon     fear     
##  4 abandon     sadness  
##  5 abandon     anger    
##  6 abandon     surprise 
##  7 abandonner  fear     
##  8 abandonner  sadness  
##  9 abandonner  anger    
## 10 abandonner  disgust
tib_mots_polarite <- tib_mots_nonvides %>%
    dplyr::left_join(proust_sentiments(), by=c("mot"="word")) 

tib_mots_polarite  %>%
  dplyr::group_by(lemma,polarity) %>% 
  dplyr::summarise(n=n()) %>% 
  dplyr::arrange(desc(n)) %>% 
  head(n=15)
## # A tibble: 15 x 3
## # Groups:   lemma [14]
##    lemma    polarity     n
##    <chr>    <chr>    <int>
##  1 <NA>     <NA>        15
##  2 thon     <NA>         5
##  3 cochon   <NA>         4
##  4 canard   <NA>         3
##  5 petit    <NA>         3
##  6 canard   positive     2
##  7 chat     positive     2
##  8 chose    <NA>         2
##  9 danser   <NA>         2
## 10 gaiement <NA>         2
## 11 poule    positive     2
## 12 préférer <NA>         2
## 13 aimable  positive     1
## 14 aimer    <NA>         1
## 15 aller    positive     1