Dans ce premier chapitre, nous nous intéressons uniquement aux mots, et non aux phrases ou aux n-grams. On peut utiliser les mêmes outils dans ces cas de figure.
1 la construction d’un corpus avec tm
Un corpus pour tm est un format de fichier particuliers. La première étape consiste à le créer à partir du vecteur de texte ( pratiquement un fichier à une colonne et autant de lignes que d’unités de textes.
tweets_corpus <- Corpus(VectorSource(tweets_text))
Les fonctions de tm vont nous permettre de nettoyer le texte, c’est à dire :
- Suppression des nombres qui n’apportent pas d’information
- Suppression de la ponctuation
- Mise en minuscule de tous les mots pour homogénéiser la morphologie.
- Suppression des stop words ( articles, pronoms, conjonctions…)
- Élimination des espaces excédentaire ( un espace marque deux mots distincts)
- Suppression de mots particuliers ( ici ceux qui ont serti à la sélection du corpus)
- Lemmatisation pour réduire à une racine unique l’ensemble des termes.
tweets_corpus <- tm_map(tweets_corpus, removeNumbers) #enlever les nombre tweets_corpus <- tm_map(tweets_corpus, removePunctuation) # ici cela va supprimer automatiquement tous les caractères de ponctuation tweets_corpus <- tm_map(tweets_corpus, content_transformer(tolower)) #mettre en minuscule tweets_corpus <- tm_map(tweets_corpus, removeWords, stopwords("french")) # ici cela va supprimer automatiquement une bonne partie des mots français "basiques", tels que "le", "la", etc. mais il en manque ! Il manque par exemple "les"... tweets_corpus <- tm_map(tweets_corpus, stripWhitespace) # ici cela va supprimer automatiquement tous les espaces vides tweets_corpus <- tm_map(tweets_corpus, removeWords,c("IA","AI", "artificiel","intelligence","artificalintelligent","artificiel","artificial","ml", "deeplearning")) #enelver le terme commun tweets_corpus <- tm_map(tweets_corpus, stemDocument, language = "french") #on cherche les radicaux des termes
Une spécificité des tweet est de contenir souvent des mentions caractérisé par le préfixe @ et des liens par http, l’utilisation de fonctions permet de résoudre ce problème. En voici un exemple pour chacun des cas :
removeURL <- function(x) gsub("http[[:alnum:][:punct:]]*", "", x) #enlever les liens tweets_corpus <- tm_map(tweets_corpus, content_transformer(removeURL)) #enlever les liens removeACC <- function(x) gsub("@\\w+", "", tweets_corpus) #enlever les comptes tweets_corpus <- tm_map(tweets_corpus, content_transformer(removeACC)) #enlever les comptes
Le nettoyage étant fait ne reste plus qu’à créer le tableau que nous allons analyser où les lignes sont les termes et les colonnes les documents ( unités de texte) avec la fonction TermDocumentMatrix. Dans l’exemple un controle est appliqué : ne sont retenu que les mots de 2 à 30 caractères.
tdm <- TermDocumentMatrix(tweets_corpus, control=list(wordLengths=c(2, 30)))
si besoin on peut créer le symétrique : un DocumentTermMatrix (dtm)
2 La même chose avec Tidyverse
Tidyverse est une alternative plus moderne qui permet de mettre en place des pipes efficaces avec l’opérateur %>%
et les verbes de dplyr .
La première étape est d’importer le corpus dans R. Dans notre cas, notre corpus est composé de 102 articles au format .txt se trouvant dans un même fichier. Le nom des documents est leur date de publication. Nous allons récupérer ces textes dans un tableau et y accoler leurs noms ainsi que l’année de publication (qui correspondent aux 4 premiers caractères du nom de l’article) :
setwd("~/Thèse/Airbnb/airbnb/airbnbcitizen")
tbl %
map_chr(~ read_file(.)) %>%
data_frame(text = .)%>%
mutate(year=substr(list.files(pattern = "*.txt"), start=1, stop=4))%>%
mutate(doc=(list.files(pattern = "*.txt")))%>%
group_by(doc,year) %>%
ungroup()
tbl
## # A tibble: 102 x 3
## text year doc
##
## 1 "\r\nAirbnb Citizen\r\nSeptember 9th, 2013\r\nBerlin and t~ 2013 2013~
## 2 "\r\nAirbnb Citizen\r\nJune 12th, 2013\r\nContributing to ~ 2013 2013~
## 3 "\r\nAirbnb Citizen\r\nOctober 21st, 2013\r\nNews from the~ 2013 2013~
## 4 "\r\nAirbnb Citizen\r\nFebruary 13th, 2014\r\nAirbnb and h~ 2014 2014~
## 5 "\r\nAirbnb Citizen\r\nApril 21st, 2014\r\nNew York and th~ 2014 2014~
## 6 "\r\nAirbnb Citizen\r\nApril 22nd, 2014\r\nStatement on He~ 2014 2014~
## 7 "\r\nAirbnb Citizen\r\nMarch 25th, 2014\r\nAirbnb economic~ 2014 2014~
## 8 "\r\nAirbnb Citizen\r\nMarch 25th, 2014\r\nAirbnb economic~ 2014 2014~
## 9 "\r\nAirbnb Citizen\r\nMarch 26th, 2014\r\nA major step fo~ 2014 2014~
## 10 "\r\nAirbnb Citizen\r\nSeptember 1st, 2015\r\nOscar\x92s N~ 2015 2015~
## # ... with 92 more rows
Nous allons maintenant découper les textes selon les mots employés :
tbl%
unnest_tokens(word, text)
tbl
## # A tibble: 54,600 x 3
## year doc word
##
## 1 2013 20130909.txt airbnb
## 2 2013 20130909.txt citizen
## 3 2013 20130909.txt september
## 4 2013 20130909.txt 9th
## 5 2013 20130909.txt 2013
## 6 2013 20130909.txt berlin
## 7 2013 20130909.txt and
## 8 2013 20130909.txt the
## 9 2013 20130909.txt airbnb
## 10 2013 20130909.txt community
## # ... with 54,590 more rows
Nous pouvons tout de suite regarder quels sont les mots les plus fréquents :
tbl %>%
count(word, sort = TRUE)
## # A tibble: 5,267 x 2
## word n
##
## 1 the 2514
## 2 to 1863
## 3 and 1754
## 4 in 1537
## 5 of 1306
## 6 airbnb 1115
## 7 a 846
## 8 for 652
## 9 we 643
## 10 that 485
## # ... with 5,257 more rows
Nous constatons que les mots les plus fréquents dans les différents articles correspondent à des mots vides, qui n’apportent pas de sens particulier mais qui servent à structurer le texte. Nous pouvons supprimer ces mots vides ( appelé aussi stopwords).
De plus, nous observons que Airbnb est très présent, ce qui est normal vu qu’il s’agit d’un corpus de textes issus d’Airbnb. Nous pouvons également supprimer ce mot du corpus sans perdre de sens. Nous allons faire de même avec le terme citizen, puisque ce mot est associé à Airbnb pour désigner le site duquel sont extraits les textes. Pour cela, nous allons ajouter ces deux termes à la liste des mots vides à supprimer, puis nous allons nettoyer le corpus :
custom_stop_words <- bind_rows(data_frame(word = c("airbnb","citizen"),
lexicon = c("custom")),
stop_words)
tbl%
anti_join(custom_stop_words)
## Joining, by = "word"
tbl %>%
count(word, sort = TRUE)
## # A tibble: 4,767 x 2
## word n
##
## 1 home 470
## 2 hosts 434
## 3 sharing 400
## 4 community 292
## 5 city 265
## 6 paris 263
## 7 guests 259
## 8 cities 251
## 9 people 210
## 10 local 207
## # ... with 4,757 more row
3 Méthodes plus élaborées
Les textes sont de nature bien différentes : un corpus de lettres manuscrites, des abstracts d’une revue scientifique, de la littérature éditées, des pages webs corporate. Chaque situation présente des spécificité importante. Quand il n’y a pas eu de travail d’édition, coquille et fautes d’orthographe ajoutent du bruit, quand le texte est élaboré il peut être intéressant de se concentrer sur certains aspects de la langue (quels objets, quels qualificatifs, quels verbes). L’écriture numérique utilisent largement d’autres marqueurs : emoji notamment.
3.1 la correction d’orthographe
Dans le cas où le texte est tapuscrit (par exemple une question ouvertes dans un questionnaire web), une correction d’orthographe pour homogénéiser la morphologie du lexique est nécessaire.
3.1 traitement des émoticon
Les emoticon fréquent dans les réseaux sociaux, peuvent être naturellement être traité comme des chaines de caractères à part entière. On en trouvera un exemple ici : http://opiateforthemass.es/articles/emoticons-in-R/
( au juste pour les enlever avec tm :
gsub("[^\x01-\x7F]", "", Texts)
3.2 POS tagging
Le traitement lexical esquissé au dessus se limite à filtrer parmi les mots ceux qui contribuent à la production de sens, et se réduit à l’analyse lexicale. Il peut être intéressant de les coder en fonction de leur nature afin de distinguer au moins les verbes, les substantifs ou les qualificatifs.
Ce type de méthodes est appelée Part Of Speech Tagging. Un certain nombre de ressources disponibles sur r pour cette tâche sont disponibles ici.