Introduction

Twitter est un réseau social créé en 2006 par Jack Dorsey, Noah Glass, Biz Stone et Evan Williams. Twitter fournit une plateforme pour partager et recevoir des messages de manière rapide, avec plus de 500 millions de tweets envoyés par jour. Le réseau social est identifié internationalement par son logo d’oiseau populairement connu sous le nom de « Larry l’oiseau» inspiré par Larry Bird des Boston Celtics de la NBA. Twitter est un service de réseautage social et de microblogging, permettant aux utilisateurs enregistrés de lire et d’afficher des messages courts, appelés tweets. Ces messages sont limités à 140 caractères.

Dans ce projet, nous allons utiliser les informations mises à disposition par Twitter afin d’étudier un phénomène qui fait l’actualité en France : le mouvement des gilets jaunes. L’objectif de ce projet est de répondre à la problématique suivante : « Quel est le profil politique des manifestants du mouvement des gilets jaunes ? »

Afin de répondre à cette question nous allons effectuer Une analyse textuelle du contenu des tweets des principaux représentants des parties majeurs en france ainsi que les représentants des gilets jaunes. Nous allons essayer de trouver un lien entre ce mouvement et les parties politiques avec les méthodes suivantes: ACP, kmeans,nuage de mots, analyse de l’état émotionnel d’un utilisateur…)

Pour effectuer ces analyses, nous utilisons un package R : twitteR. De plus, Twitter autorise les utilisateurs qui en font la demande de récupérer des données via des APIs. Une fois notre compte validé, il nous a suffi de renseigner les paramètres suivants : api_key, api_secret, access_token, access_token_secret qui sont fournis par l’API Twitter pour récupérer des tweets.

A prendre en compte: À l’origine plutôt ouvert, le réseau social est devenu de plus en plus fermé sur l’utilisation d’APIs (indispensable afin de récolter des données tels que des tweets). Cette stratégie a entraîné la fermeture de plusieurs projets tiers, et notamment de clients Twitter, ou d’outils d’analyse. Dernièrement, Twitter a supprimé l’API « compteur de Tweets » permettant aux médias d’indiquer dans les articles combien de fois un article avait été partagé. Durant notre projet, on a donc été limité par des restrictions tels que la quantité de tweets récoltés, l’intervalle de temps sur laquelle on peut les obtenir, la géolocalisation etc…

Récuperation de tweets via twitteR

Packages

Durant ce projet les packages suivants seront utilisés:

library(NLP)
library(twitteR) 
library(stringr)
library(tm)
library(RColorBrewer)
library(wordcloud)
library(SnowballC)
library(openxlsx)
library(cluster)
library(FactoMineR)
library(ggplot2)
library(syuzhet)
library(stringi)
library(topicmodels)

Récupération de tweets via APIs effectuée le 4/02/2019

Notre stratégie: Cibler les comptes Twitter des représentants des principaux parties politiques ainsi que ceux du mouvement des gilets jaunes. Pour cela nous allons essayer de récupérer les 900 derniers tweets par groupe avec les codes suivants:

A noté: Il a été facile d’avoir 900 tweets de la part de politiciens. il nous a suffi de récupérer 300 dernier tweets de 3 politiciens. Pour les gilets jaunes il nous a fallu 6 comptes twitter pour arriver à 889 tweets.

## Récupération tweets des Gilets Jaunes et conversion en dataframe

#Jerome Rodrigues
JR_tweet = userTimeline("J_Rodrigues_Off", n=300, includeRts = TRUE)
JR_tweet_df = twListToDF(JR_tweet)

#Maxime Nicolle
Nicolle_tweet = userTimeline("FlyRiderGj", n=300, includeRts = TRUE)
Nicolle_tweet_df = twListToDF(Nicolle_tweet)

#Priscillia Ludosky

Ludosky_tweet = userTimeline("PLudosky", n=300, includeRts = TRUE)
Ludosky_tweet_df = twListToDF(Ludosky_tweet)

#François Boulo 
FB_tweet = userTimeline("BouloGiletJaune", n=300, includeRts = TRUE)
FB_tweet_df = twListToDF(FB_tweet)

#Benjamin cauchy
BC_tweet = userTimeline("BenjaminCauchy", n=300, includeRts = TRUE)
BC_tweet_df = twListToDF(BC_tweet)

#Eric Drouet
Drouet_tweet = userTimeline("EricDrouetGJ", n=300, includeRts = TRUE)
Drouet_tweet_df = twListToDF(BC_tweet)

# Aggrégation des tweets_df des GJ
GJ_tweet_df=rbind(JR_tweet_df,Nicolle_tweet_df,Ludosky_tweet_df,FB_tweet_df,BC_tweet_df,Drouet_tweet_df )
## Récupération tweets du parti Les républicains et conversion en dataframe

#Edouard philippe
EP_tweet = userTimeline("EPhilippePM", n=300, includeRts = TRUE)
EP_tweet_df = twListToDF(EP_tweet)

#Alain Juppe
AJ_tweet = userTimeline("alainjuppe", n=300, includeRts = TRUE)
AJ_tweet_df = twListToDF(AJ_tweet)

#Laurent Wauquiez
LW_tweet = userTimeline("laurentwauquiez", n=300, includeRts = TRUE)
LW_tweet_df = twListToDF(LW_tweet)

# Aggrégation des tweets_df des LR
LR_tweet_df=rbind(EP_tweet_df,AJ_tweet_df,LW_tweet_df)
## Récupération tweets du parti La République En Marche et conversion en dataframe

#Benjamin Griveaux
BG_tweet = userTimeline("BGriveaux", n=300, includeRts = TRUE)
BG_tweet_df = twListToDF(BG_tweet)

#Emmanuel Macron
EM_tweet = userTimeline("EmmanuelMacron", n=300, includeRts = TRUE)
EM_tweet_df = twListToDF(EM_tweet)

#Christophe Castaner
CC_tweet = userTimeline("CCastaner", n=300, includeRts = TRUE)
CC_tweet_df = twListToDF(CC_tweet)

# Aggrégation des tweets_df des RM
RM_tweet_df=rbind(BG_tweet_df,EM_tweet_df,CC_tweet_df)
## Récupération tweets du parti La France Insoumise et conversion en dataframe

#Jean-Luc Mélenchon
JM_tweet = userTimeline("JLMelenchon", n=300, includeRts = TRUE)
JM_tweet_df = twListToDF(JM_tweet)

#Adrien Quatennens
AQ_tweet = userTimeline("AQuatennens", n=300, includeRts = TRUE)
AQ_tweet_df = twListToDF(AQ_tweet)

#Alexis Corbière
AC_tweet = userTimeline("alexiscorbiere", n=300, includeRts = TRUE)
AC_tweet_df = twListToDF(AC_tweet)

# Aggrégation des tweets_df des FI
FI_tweet_df=rbind(JM_tweet_df,AQ_tweet_df,AC_tweet_df)
## Récupération tweets du parti Le Rassemblement National et conversion en dataframe

#Marine Le Pen
MP_tweet = userTimeline("MLP_officiel", n=300, includeRts = TRUE)
MP_tweet_df = twListToDF(MP_tweet)

#Gilbert Collard
GC_tweet = userTimeline("GilbertCollard", n=300, includeRts = TRUE)
GC_tweet_df = twListToDF(GC_tweet)

#Jordan Bardella
JB_tweet = userTimeline("J_Bardella", n=300, includeRts = TRUE)
JB_tweet_df = twListToDF(JB_tweet)

# Aggrégation des tweets_df des RN
RN_tweet_df=rbind(MP_tweet_df,GC_tweet_df,JB_tweet_df)

Ci-dessous un tableau récapitulatif du nombre de tweets récupérés ainsi que leur provenance (le code couleur sera respecté tout au long du rapport):

Nettoyage du texte (plus d’accents, de liens et de divers caractères spéciaux)

source : https://www.math.u-bordeaux.fr/~arichou/site/projets2017/Camara-Canal.html

clean.text = function(x_text, word = stopwords("fr"), lang = "fr")
{
  if (lang == "fr"){
    x_text = str_replace_all(x_text, "à", "a")
    x_text = str_replace_all(x_text, "â", "a")
    x_text = str_replace_all(x_text, "ç", "c")
    x_text = str_replace_all(x_text, "é", "e")
    x_text = str_replace_all(x_text, "è", "e")
    x_text = str_replace_all(x_text, "ê", "e")
    x_text = str_replace_all(x_text, "ù", "u")
    x_text = str_replace_all(x_text, "ï", "i")
    x_text = str_replace_all(x_text, "û", "u")
    x_text = str_replace_all(x_text, "ô", "o")
    x_text = str_replace_all(x_text, "î", "i")
  }
  x_text = sapply(x_text,function(x) iconv(x, "latin1", "ASCII", sub="")) 
  x_text = str_replace_all(x_text, "(RT|via)((?:\\b\\W*@\\w+)+)", " ")
  x_text = str_replace_all(x_text, "(\r)", " ")
  x_text = str_replace_all(x_text, "@\\w+", " ")
  x_text = str_replace_all(x_text, "http.+", " ")
  x_text = str_replace_all(x_text, "[[:punct:]]", " ")
  x_text = str_replace_all(x_text, "[[:digit:]]", " ")
  x_text = str_replace_all(x_text, "[ \t]{2,}", " ") 
  x_text = str_replace_all(x_text, "^\\s+|\\s+$", "")
  x_text = str_replace_all(x_text, "[^\x01-\x7F<>+]", "")
  
 
  
  x_text = str_trim(x_text)
  return(x_text)
}
#Récupération texte de chaque data frame 
LR_text=LR_tweet_df$text
RM_text=RM_tweet_df$text
FI_text=FI_tweet_df$text
RN_text=RN_tweet_df$text
GJ_text=GJ_tweet_df$text


#Nettoyage des textes
LR_text=clean.text(LR_text)
RM_text=clean.text(RM_text)
FI_text=clean.text(FI_text)
RN_text=clean.text(RN_text)
GJ_text=clean.text(GJ_text)

Les tweets sont maintenant “propres”, nous pouvons commençer à les analyser!

Analyse en Composantes Principales (ACP)

########################## ACP ##################################


# Couper la liste des tweets de chaque parti en 10 sous-listes aléatoirement
# Cela veut dire qu'on regroupe les tweets par packet de 90.
set.seed(75)
n=10
FISplit<- split(FI_text, sample(rep(1:n, length.out = length(FI_text))))
RMSplit<- split(RM_text, sample(rep(1:n, length.out = length(RM_text))))
LRSplit <- split(LR_text, sample(rep(1:n, length.out = length(LR_text))))
RNSplit <- split(RN_text, sample(rep(1:n, length.out = length(RN_text))))
GJSplit <- split(GJ_text, sample(rep(1:n, length.out = length(GJ_text))))

# Aggréger les tweets d'un même groupe de tweets
FIGroup <- lapply(FISplit , function(x) paste(x, collapse = " "))
RMGroup <- lapply(RMSplit , function(x) paste(x, collapse = " "))
LRGroup <- lapply(LRSplit , function(x) paste(x, collapse = " "))
RNGroup <- lapply(RNSplit , function(x) paste(x, collapse = " "))
GJGroup <- lapply(GJSplit , function(x) paste(x, collapse = " "))
all <- c(FIGroup, RMGroup, LRGroup, RNGroup, GJGroup)

# corpus
corpus.all = Corpus(VectorSource(all))
# convert to lower case
corpus.all= tm_map(corpus.all, tolower)
# remove stoprwords
corpus.all = tm_map(corpus.all, removeWords, c(stopwords("french")))
# remove extra white-spaces
corpus.all = tm_map(corpus.all, stripWhitespace)
# term-document matrix
tdm = TermDocumentMatrix(corpus.all)
# convert as matrix
all_matrix = as.matrix(tdm)
all_matrix_t=t(all_matrix)

#### Nous transformons cette matrice pour obtenir la fréquence des mots, 
#####autrement dit le nombre d'occurrences divisé par le nombre total d'un groupe de tweets donné.
  
somme_ligne = rowSums(all_matrix_t)
all_matrix_freq=all_matrix_t/somme_ligne
label=c(rep("FI",10),rep("RM",10),rep("LR",10),rep("RN",10),rep("GJ",10))
class(all_matrix_freq) <- "numeric"
all_dataframe <- as.data.frame(all_matrix_freq)
all_dataframe_label=cbind(all_dataframe,label)



#ACP: Chaque observation correponds à un regroupement de 90 tweets labélisés par partie. Ici les variables sont les fréquences des mots utilités dans le groupe de tweet.
library(FactoMineR) 
#library(PCAmixdata)
res <- PCA(all_dataframe_label, quali.sup=9226, graph=FALSE, scale.unit = TRUE, ncp = 10) # original data in input
plot(res,choix="ind", axes = c(1,2), cex=1.5,title="", habillage = 9226, label="none", invisible = "quali")
title(main = "ACP de tweets sur les dimensions 1 et 2")

plot(res,choix="ind", axes = c(1,3), cex=1.5,title="", habillage = 9226,label="none")
title(main = "ACP de tweets sur les dimensions 1 et 3")

plot(res,choix="ind", axes = c(2,3), cex=1.5,title="", habillage = 9226, label="none")
title(main = "ACP de tweets sur les dimensions 2 et 3")

Résultat: SUr les dimensions 1-2, 1-3 ou 2-3 les tweets du parti de la france insoumise, du rassemblement national ainsi que ds gilets jaunes sont semblables (proche sur les plans). Ils sembleraient donc que les Gilets Jaunes partagent les mêmes idées que les partis extrêmes en France. Comment montrer ces liens?

Top mots utilisés

Une première approche est de comparer les mots les plus utilisés par les diffénts groupes:

Tops mots du parti Les Républicains

################### LR fréquence mots ######################
# corpus
LR_corpus = Corpus(VectorSource(LR_text))
# convertir en minuscule
LR_corpus = tm_map(LR_corpus, tolower)
# supprimer les mots courants
LR_corpus = tm_map(LR_corpus, removeWords, stopwords("french"))
# Supprimer les extra espaces blancs
LR_corpus = tm_map(LR_corpus, stripWhitespace)
# term-document matrix
tdm = TermDocumentMatrix(LR_corpus)
# convertir en matrice
LR_matrix = as.matrix(tdm)

wf = rowSums(LR_matrix)  #word frequence
LR_matrix_wf=cbind(LR_matrix,wf)
LR_matrix_wf_sort <- LR_matrix_wf[order(wf,decreasing=T),] # tri décroissant en fonction de la colonne wf

#top-40 par fréquence
top40 = head(LR_matrix_wf_sort[,901], 40)
# barplot
barplot(top40, border=NA, las=2, main="Top 40 des mots les plus utilisés par les représentants des républicains", cex.main=1)

Tops mots du parti La République En Marche

# corpus
RM_corpus = Corpus(VectorSource(RM_text))
# convert to lower case
RM_corpus = tm_map(RM_corpus, tolower)
# remove stoprwords
RM_corpus = tm_map(RM_corpus, removeWords, c(stopwords("french"),stopwords("english"), "giletsjaunes"))
# remove extra white-spaces
RM_corpus = tm_map(RM_corpus, stripWhitespace)
# term-document matrix
tdm = TermDocumentMatrix(RM_corpus)
# convert as matrix
RM_matrix = as.matrix(tdm)

wf = rowSums(RM_matrix)  #wordfrequence
RM_matrix_wf=cbind(RM_matrix,wf)
RM_matrix_wf_sort <- RM_matrix_wf[order(wf,decreasing=T),] # tri décroissant en fonction de la colonne wf

#top-40 most frequent
top40 = head(RM_matrix_wf_sort[,901], 40)
# barplot
barplot(top40, border=NA, las=2, main="Top 40 des mots les plus utilisés par les représentants de la république en marche", cex.main=1)

Tops mots du parti La France Insoumise

# corpus
FI_corpus = Corpus(VectorSource(FI_text))
# convert to lower case
FI_corpus = tm_map(FI_corpus, tolower)
# remove stoprwords
FI_corpus = tm_map(FI_corpus, removeWords, stopwords("french"))
# remove extra white-spaces
FI_corpus = tm_map(FI_corpus, stripWhitespace)
# term-document matrix
tdm = TermDocumentMatrix(FI_corpus)
# convert as matrix
FI_matrix = as.matrix(tdm)

wf = rowSums(FI_matrix)  #wordfrequence
FI_matrix_wf=cbind(RM_matrix,wf)
FI_matrix_wf_sort <- FI_matrix_wf[order(wf,decreasing=T),] # tri décroissant en fonction de la colonne wf

#top-40 most frequent
top40 = head(FI_matrix_wf_sort[,901], 40)
# barplot
barplot(top40, border=NA, las=2, main="Top 40 des mots les plus utilisés par les représentants de la france insoumise", cex.main=1)

Tops mots du parti Le Rassemblement Nationale

# corpus
RN_corpus = Corpus(VectorSource(RN_text))
# convert to lower case
RN_corpus = tm_map(RN_corpus, tolower)
# remove stoprwords
RN_corpus = tm_map(RN_corpus, removeWords,stopwords("french"))
# remove extra white-spaces
RN_corpus = tm_map(RN_corpus, stripWhitespace)
# term-document matrix
tdm = TermDocumentMatrix(RN_corpus)
# convert as matrix
RN_matrix = as.matrix(tdm)

wf = rowSums(RN_matrix)  #wordfrequence
RN_matrix_wf=cbind(RN_matrix,wf)
RN_matrix_wf_sort <- RN_matrix_wf[order(wf,decreasing=T),] # tri décroissant en fonction de la colonne wf


#top-40 most frequent
RN_matrix_wf_sort <- RN_matrix_wf_sort[,901]
top40 = head(RN_matrix_wf_sort, 40)
# barplot
barplot(top40, border=NA, las=2, main="Top 40 des mots les plus utilisés par les représentants du rassemblement national", cex.main=1)

Tops mots des Gilets Jaunes

# corpus
GJ_corpus = Corpus(VectorSource(GJ_text))
# convert to lower case
GJ_corpus = tm_map(GJ_corpus, tolower)
# remove stoprwords
GJ_corpus = tm_map(GJ_corpus, removeWords,stopwords("french"))
# remove extra white-spaces
GJ_corpus = tm_map(GJ_corpus, stripWhitespace)
# term-document matrix
tdm = TermDocumentMatrix(GJ_corpus)
# convert as matrix
GJ_matrix = as.matrix(tdm)

wf = rowSums(GJ_matrix)  #wordfrequence
GJ_matrix_wf=cbind(GJ_matrix,wf)
GJ_matrix_wf_sort <- GJ_matrix_wf[order(wf,decreasing=T),] # tri décroissant en fonction de la colonne wf

#top-40 most frequent
GJ_matrix_wf_sort <- GJ_matrix_wf_sort[,890]
top40 = head(GJ_matrix_wf_sort, 40)
# barplot
barplot(top40, border=NA, las=2, main="Top 40 des mots les plus utilisés par les représentants des gilets jaunes", cex.main=1)

Résultats: Il est extremement difficile d’analyser le lien entre les différents groupes à partir des top mots représenté en barplot. Cette approche n’est pas appropriée à notre problème. Il existe un outil plus efficace appelé le nuage de mot qui est plus adapté.

Nuage de mots

Nuage de mots Gilets jaunes

Etudions les mots utilisés par les représentants des gilets jaunes.

Drouet_text = Drouet_tweet_df$text
Ludosky_text = Ludosky_tweet_df$text
Nicolle_text = Nicolle_tweet_df$text
JR_text = JR_tweet_df$text
FB_text = FB_tweet_df$text
BC_text = BC_tweet_df$text


Drouet_text=clean.text(Drouet_text)
Ludosky_text=clean.text(Ludosky_text)
Nicolle_text=clean.text(Nicolle_text)
JR_text=clean.text(JR_text)
FB_text=clean.text(FB_text)
BC_text=clean.text(BC_text)

Drouet = paste(Drouet_text, collapse=" ")
Ludosky = paste(Ludosky_text, collapse=" ")
Nicolle = paste(Nicolle_text, collapse=" ")
Jerome = paste(JR_text, collapse=" ")
Francois=paste(FB_text, collapse=" ")
Benjamin=paste(BC_text, collapse=" ")



all = c(Drouet, Ludosky, Nicolle,Jerome,Francois,Benjamin)
corpus = Corpus(VectorSource(all))
corpus = tm_map(corpus, removeWords, stopwords("french"))
tdm = TermDocumentMatrix(corpus)
tdm = as.matrix(tdm)
# add column names
colnames(tdm) = c("Eric Drouet", "Priscillia Ludosky", "Maxime Nicolle","Jerome Rodriguez","Francois Boulo","Benjamin Cauchy")
comparison.cloud(tdm, random.order=FALSE, colors = c("#00B2FF", "red", "#FF0099","#000000","green","orange"), title.size=1.5, max.words=250)

Le nuage de comparaison nous montre la différence de fréquence des mots utilisés entre différents acteurs. Nous allons, ci-dessous, utiliser cette méthode pour comparer les fréquences des mots utilisés par les différents partis politiques avec ceux des gilets jaunes. Nous traçerons aussi le nuage de mots communs afin de voir la fréquence des mots communs utilisés, qui est plus adapté pour expliquer les liens entre des tweets de différents groupes.

Nuage de comparaison et de mots communs entre les Républicains et les gilets Jaunes

LR = paste(LR_text, collapse=" ")
GJ = paste(GJ_text, collapse=" ")

all = c(LR, GJ)
corpus = Corpus(VectorSource(all))
corpus = tm_map(corpus, removeWords, stopwords("french"))
tdm = TermDocumentMatrix(corpus)
tdm = as.matrix(tdm)
# add column names
colnames(tdm) = c("LR", "GJ")

# comparison cloud

#dev.new(width = 550, height = 500, unit = "px")
comparison.cloud(tdm, random.order=FALSE, colors = c("#10A91B", "red"), title.size=1.5, max.words=250)

commonality.cloud(tdm, random.order=FALSE, colors = c("orange"), title.size=1.5, max.words=250)

Nuage de comparaison et de mots communs entre la République En Marche et les gilets Jaunes

RM = paste(RM_text, collapse=" ")
GJ = paste(GJ_text, collapse=" ")

all = c(RM, GJ)
corpus = Corpus(VectorSource(all))
corpus = tm_map(corpus, removeWords, stopwords("french"))
tdm = TermDocumentMatrix(corpus)
tdm = as.matrix(tdm)
# add column names
colnames(tdm) = c("RM", "GJ")

# comparison cloud

#dev.new(width = 550, height = 500, unit = "px")
comparison.cloud(tdm, random.order=FALSE, colors = c("#102AA9", "red"), title.size=1.5, max.words=250)

commonality.cloud(tdm, random.order=FALSE, colors = c("orange"), title.size=1.5, max.words=250)

Nuage de comparaison et de mots communs entre la France insoumise et les gilets Jaunes

FI = paste(FI_text, collapse=" ")
GJ = paste(GJ_text, collapse=" ")

all = c(FI, GJ)
corpus = Corpus(VectorSource(all))
corpus = tm_map(corpus, removeWords, stopwords("french"))
tdm = TermDocumentMatrix(corpus)
tdm = as.matrix(tdm)
# add column names
colnames(tdm) = c("FI", "GJ")

# comparison cloud

#dev.new(width = 550, height = 500, unit = "px")
comparison.cloud(tdm, random.order=FALSE, colors = c("#000000", "red"), title.size=1.5, max.words=250)

commonality.cloud(tdm, random.order=FALSE, colors = c("orange"), title.size=1.5, max.words=250)

Nuage de comparaison et de mots communs entre le Rassemblement National et les gilets Jaunes

RN = paste(RN_text, collapse=" ")
GJ = paste(GJ_text, collapse=" ")

all = c(RN, GJ)
corpus = Corpus(VectorSource(all))
corpus = tm_map(corpus, removeWords, stopwords("french"))
tdm = TermDocumentMatrix(corpus)
tdm = as.matrix(tdm)
# add column names
colnames(tdm) = c("RN", "GJ")

# comparison cloud

#dev.new(width = 550, height = 500, unit = "px")
comparison.cloud(tdm, random.order=FALSE, colors = c("#31D4C9", "red"), title.size=1.5, max.words=250)

commonality.cloud(tdm, random.order=FALSE, colors = c("orange"), title.size=1.5, max.words=250)

Résultat: On peut observer à travers les différents nuages de comparaisons (1er plot de chaque partie), les différences de fréquences des mots utilisés entre chaque partis politiques et les gilets jaunes. Le nuage de mots communs (2 eme plot de chaque partie), nous montre le résultat le plus intérressant: Le terme “giletsjaunes” est au centre de chaque nuage pour le Rassemblement national ainsi que pour la France insoumise. Ce qui signifie que ce terme est très utilisé par ces 2 parties. Ce qui peut expliquer leurs rapprochements sur l’ACP. Isolons ce terme, et traçons un barplot de ses occurences dans les tweets récoltés:

barplot(occ.data$Occurence_term_giletsjaunes, names = occ.data$partie,
        xlab = "Parties", ylab = "Occurences terme giletsjaunes",
        main = "Nombre de fois le terme 'giletsjaunes' a été utilisé par partie")

Ce barplot confirme que les gilets Jaunes sont très soutenus par les partis comme le Rassemblement National et la France Insoumise. Le score de la république en marche et des républicains est très bas, ces partis préfèrent donc ne pas nommer les manifestants par les “gilets jaunes” dans leur tweet.

Classification des mots utilisés par thème

Nous allons essayer dans cette partie de classifié les top 200 mots utilisés par chaque groupe en des thèmes communs en utilisant une analyse factorielle et de l’apprentissage non supervisé avec les Kmeans. Nous déterminerons les nombres de classes avec la “méthode des coudes” trouvé sur https://thinkr.fr/premiers-pas-en-machine-learning-avec-r-volume-3-k-means-clustering/

Thèmes principaux des tweets des Républicains

# dataframe des 200 termes les plus fréquents
matrix_top200 = LR_matrix_wf_sort[1:200,-901]

# Elimine tous le colonnes avec que des zéros
matrix_top200 = matrix_top200[,colSums(matrix_top200)!=0]

#Nbr cluster?
ratio_ss <- data.frame(cluster = seq(from = 1, to = 30, by = 1)) 
for (k in 1:30) {
  km_model <- kmeans(matrix_top200, k, nstart = 20)
  ratio_ss$ratio[k] <- km_model$tot.withinss / km_model$totss
}

ggplot(ratio_ss, aes(cluster, ratio)) + ggtitle("Technique coude pour trouver le nombre de cluster k optimale")+
  geom_line() +
  geom_point()

# Analyse factorielle
result_ca = CA(matrix_top200, graph=FALSE)

# Découpage en 8 clusters
k = 4
# Kmeans
result_k_means = kmeans(result_ca$row$coord[,1:2], k)

# Obtenir clusters
clusters = result_k_means$cluster
# création data frame
rei_words_df = data.frame(
  words = rownames(matrix_top200),
  dimatrix_top200 = result_ca$row$coord[,1],
  dim2 = result_ca$row$coord[,2],
  freq = rowSums(matrix_top200),
  cluster = as.factor(clusters))
# plot
ggplot(rei_words_df, aes(x=dimatrix_top200, y=dim2, label=words)) + ggtitle("Analyse factorielle des principaux mots de tweets des républicains")+
  geom_text(aes(size=freq, colour=cluster), alpha=0.7) +
  scale_size_continuous(breaks=seq(20,80,by=10), range=c(3,8)) +
  scale_colour_manual(values=brewer.pal(8, "Dark2")) +
  labs(x="", y="") 

Thèmes principaux des tweets de la République En Marche

# dataframe des 200 termes les plus fréquents
matrix_top200 = RM_matrix_wf_sort[1:200,-901]


# Elimine tous le colonnes avec que des zéros
matrix_top200 = matrix_top200[,colSums(matrix_top200)!=0]

#Nbr cluster?
ratio_ss <- data.frame(cluster = seq(from = 1, to = 30, by = 1)) 
for (k in 1:30) {
  km_model <- kmeans(matrix_top200, k, nstart = 20)
  ratio_ss$ratio[k] <- km_model$tot.withinss / km_model$totss
}

ggplot(ratio_ss, aes(cluster, ratio)) + ggtitle("Technique coude pour trouver le nombre de cluster k optimale")+
  geom_line() +
  geom_point()

# Analyse factorielle
result_ca = CA(matrix_top200, graph=FALSE)

# Découpage en 8 clusters
k = 3
# Kmeans
result_k_means = kmeans(result_ca$row$coord[,1:2], k)

# Obtenir clusters
clusters = result_k_means$cluster
# création data frame
rei_words_df = data.frame(
  words = rownames(matrix_top200),
  dimatrix_top200 = result_ca$row$coord[,1],
  dim2 = result_ca$row$coord[,2],
  freq = rowSums(matrix_top200),
  cluster = as.factor(clusters))
# plot
ggplot(rei_words_df, aes(x=dimatrix_top200, y=dim2, label=words)) + ggtitle("Analyse factorielle des principaux mots de tweets de la république en marche")+
  geom_text(aes(size=freq, colour=cluster), alpha=0.7) +
  scale_size_continuous(breaks=seq(20,80,by=10), range=c(3,8)) +
  scale_colour_manual(values=brewer.pal(8, "Dark2")) +
  labs(x="", y="") 

Thèmes principaux des tweets de la France Insoumise

# dataframe des 200 termes les plus fréquents
matrix_top200 = FI_matrix_wf_sort[1:200,-901]

# Elimine tous le colonnes avec que des zéros
matrix_top200 = matrix_top200[,colSums(matrix_top200)!=0]

#Nbr cluster?
ratio_ss <- data.frame(cluster = seq(from = 1, to = 30, by = 1)) 
for (k in 1:30) {
  km_model <- kmeans(matrix_top200, k, nstart = 20)
  ratio_ss$ratio[k] <- km_model$tot.withinss / km_model$totss
}

ggplot(ratio_ss, aes(cluster, ratio)) + ggtitle("Technique coude pour trouver le nombre de cluster k optimale")+
  geom_line() +
  geom_point()

# Analyse factorielle
result_ca = CA(matrix_top200, graph=FALSE)

# Découpage en 8 clusters
k = 4
# Kmeans
result_k_means = kmeans(result_ca$row$coord[,1:2], k)

# Obtenir clusters
clusters = result_k_means$cluster
# création data frame
rei_words_df = data.frame(
  words = rownames(matrix_top200),
  dimatrix_top200 = result_ca$row$coord[,1],
  dim2 = result_ca$row$coord[,2],
  freq = rowSums(matrix_top200),
  cluster = as.factor(clusters))
# plot
ggplot(rei_words_df, aes(x=dimatrix_top200, y=dim2, label=words)) + ggtitle("Analyse factorielle des principaux mots de tweets de la france insoumise")+
  geom_text(aes(size=freq, colour=cluster), alpha=0.7) +
  scale_size_continuous(breaks=seq(20,80,by=10), range=c(3,8)) +
  scale_colour_manual(values=brewer.pal(8, "Dark2")) +
  labs(x="", y="") 

Thèmes principaux des tweets du Rassemblement National

# dataframe des 200 termes les plus fréquents
matrix_top200 = RN_matrix_wf[order(wf,decreasing=T),]
matrix_top200 = matrix_top200[1:200,-901]

# Elimine tous le colonnes avec que des zéros
matrix_top200 = matrix_top200[,colSums(matrix_top200)!=0]

#Nbr cluster?
ratio_ss <- data.frame(cluster = seq(from = 1, to = 30, by = 1)) 
for (k in 1:30) {
  km_model <- kmeans(matrix_top200, k, nstart = 20)
  ratio_ss$ratio[k] <- km_model$tot.withinss / km_model$totss
}

ggplot(ratio_ss, aes(cluster, ratio)) + ggtitle("Technique coude pour trouver le nombre de cluster k optimale")+
  geom_line() +
  geom_point()

# Analyse factorielle
result_ca = CA(matrix_top200, graph=FALSE)

# Découpage en 3 clusters
k = 3
# Kmeans
result_k_means = kmeans(result_ca$row$coord[,1:2], k)

# Obtenir clusters
clusters = result_k_means$cluster
# création data frame
rei_words_df = data.frame(
  words = rownames(matrix_top200),
  dimatrix_top200 = result_ca$row$coord[,1],
  dim2 = result_ca$row$coord[,2],
  freq = rowSums(matrix_top200),
  cluster = as.factor(clusters))
# plot
ggplot(rei_words_df, aes(x=dimatrix_top200, y=dim2, label=words)) + ggtitle("Analyse factorielle des principaux mots de tweets du rassemblement national")+
  geom_text(aes(size=freq, colour=cluster), alpha=0.7) +
  scale_size_continuous(breaks=seq(20,80,by=10), range=c(3,8)) +
  scale_colour_manual(values=brewer.pal(8, "Dark2")) +
  labs(x="", y="") 

Thèmes principaux des tweets des Gilets Jaunes

# dataframe des 200 termes les plus fréquents
matrix_top200 = GJ_matrix_wf[order(wf,decreasing=T),]
matrix_top200 = matrix_top200[1:200,-853]

# Elimine tous le colonnes avec que des zéros
matrix_top200 = matrix_top200[,colSums(matrix_top200)!=0]

#Nbr cluster?
ratio_ss <- data.frame(cluster = seq(from = 1, to = 9, by = 1)) 
for (k in 1:9) {
  km_model <- kmeans(matrix_top200, k, nstart = 20)
  ratio_ss$ratio[k] <- km_model$tot.withinss / km_model$totss
}

ggplot(ratio_ss, aes(cluster, ratio)) + ggtitle("Technique coude pour trouver le nombre de cluster k optimale")+
  geom_line() +
  geom_point()

# Analyse factorielle
result_ca = CA(matrix_top200, graph=FALSE)

# Découpage en 2 clusters
k = 2
# Kmeans
result_k_means = kmeans(result_ca$row$coord[,1:2], k)

# Obtenir clusters
clusters = result_k_means$cluster
# création data frame
rei_words_df = data.frame(
  words = rownames(matrix_top200),
  dimatrix_top200 = result_ca$row$coord[,1],
  dim2 = result_ca$row$coord[,2],
  freq = rowSums(matrix_top200),
  cluster = as.factor(clusters))
# plot
ggplot(rei_words_df, aes(x=dimatrix_top200, y=dim2, label=words)) + ggtitle("Analyse factorielle des principaux mots de tweets des gilets jaunes")+
  geom_text(aes(size=freq, colour=cluster), alpha=0.7) +
  scale_size_continuous(breaks=seq(20,80,by=10), range=c(3,8)) +
  scale_colour_manual(values=brewer.pal(8, "Dark2")) +
  labs(x="", y="") 

Résultat: Des groupes de mots apparaissent. Mais il est difficile de les étiquetter. Pour cela nous pouvons nous aider des principaux Hashtags liés aux tweets récupérés.

Etude des Hashtags

Principaux Hashtags des différents acteurs afin de nous aider à trouver les thèmes dans la clusterisation k means

# load packages
library(stringr)
library(wordcloud)



# get the hashtags
LR_hashtags = str_extract_all(LR_tweet_df$text, "#\\w+")
RM_hashtags = str_extract_all(RM_tweet_df$text, "#\\w+")
FI_hashtags = str_extract_all(FI_tweet_df$text, "#\\w+")
RN_hashtags = str_extract_all(RN_tweet_df$text, "#\\w+")
GJ_hashtags = str_extract_all(GJ_tweet_df$text, "#\\w+")


# put tags in vector
LR_hashtags = unlist(LR_hashtags)
RM_hashtags = unlist(RM_hashtags)
FI_hashtags = unlist(FI_hashtags)
RN_hashtags = unlist(RN_hashtags)
GJ_hashtags = unlist(GJ_hashtags)

# calculate hashtag frequencies
LR_tags_freq = table(LR_hashtags)
RM_tags_freq = table(RM_hashtags)
FI_tags_freq = table(FI_hashtags)
RN_tags_freq = table(RN_hashtags)
GJ_tags_freq = table(GJ_hashtags)


# put all tags in a single vector
all_tags = c(LR_tags_freq, RM_tags_freq, FI_tags_freq,RN_tags_freq,GJ_tags_freq)


# vector of colors
cols = c(
  rep("#1D18C3", length(LR_tags_freq)),
  rep("#000000", length(RM_tags_freq)),
  rep("#C52C51", length(FI_tags_freq)),
  rep("#928A7E", length(RN_tags_freq)),
  rep("#FEB102", length(GJ_tags_freq))
)

# wordcloud

wordcloud(names(all_tags), all_tags, random.order=FALSE, min.freq=1, 
          colors=cols, ordered.colors=TRUE)

Analyse de sentiments

L’analyse de sentiments (Sentiment Analysis) est l’un des thèmes les plus fascinants dans l’analyse textuelle de tweets. Cette analyse permet de ressortir l’opinion et l’attitude d’une population concernant un sujet particulier, en effet Twitter permet d’acceder à un échantillon relativement significatif de la population sans pour autant avoir besoin de créer de sondages. Cependant la détéction d’émotions est une tâche très difficile notemment à cause de la nature complèxe de chaque langue, et du type de langages et des nuances présentes dans les tweets de chacun. L’analyse de sentiment peut avoir differentes fonction : une entreprise qui cherche à comprendre l’avis d’une population sur un produit ou un service peut notemment avoir recours à une analyse de sentiments.

Nous allons, dans cette partie proceder à une analyse des sentiments reflètent les Tweets récuperés à l’aide de la fonction “searchTwitter” du package “twitteR”. Pour ce faire, nous aurons besoin du package “syuzhet”.

Gilets Jaunes

Visualisation des sentiments (fréquences)

Nous récuperons les Tweets en français, ces Tweets vont être mis en forme et prétraités pour pouvoir extraire l’information voulue, en l’occurence ici “les scores” des sentiments généraux derrière les Tweets #giletsjaunes.

tweets_gj <- searchTwitter("#giletsjaunes", n=1000,lang = "fr")
gj_tweets <- twListToDF(tweets_gj)
gj_text<- gj_tweets$text

Nous utilisons la fonction “get_nrc_sentiment” du package “syuzhet”, cette dernière permet d’attribuer à chaque Tweet une note sur chacun des sentiments.

Cette fonction procède en traitant chaque Tweet et en faisant appel au dictionnaire “NRC” et en évaluant la presence de mots qui reflètent l’un des 10 sentiments :

  • Colère
  • Impatience
  • Dégoût
  • Peur
  • Joie
  • Négativité
  • Positivité
  • Tristesse
  • Surprise
  • Confiance

Ici nous avons effectué une analyse sur #giletsjaunes, c’est un mouvement qui évoque diverses émotions chez la populations, que ce soit de part leur affiliation politique, ou l’impact qu’a eu ce mouvement sur leurs quotidien. Il est alors fascinant d’avoir une idée sur l’opinion des personnes qui ont tweeté au moment de notre analyse.

ggplot(data=Sentimentscores_gj,aes(x=sentiment,y=Score))+geom_bar(aes(fill=sentiment),stat = "identity")+
  theme(legend.position="none")+
  xlab("Sentiments")+ylab("scores")+ggtitle("Sentiments des gens qui twittent #giletsjaunes")

Visualisation des sentiments (fréquences) Paris

Il peut aussi être intéressant de voir les differents “score” des sentiments du dictionnaire NRC dans differentes régions, ici nous avons éffectué l’étude dans la région parisienne, dans un rayon de 100km avec l’argument “geocode” de la fonction searchTwitter.

tweets_gj <- searchTwitter("#giletsjaunes", n=1000,lang = "fr", geocode = "48.8,2.3,100km")
gj_tweets <- twListToDF(tweets_gj)
gj_text<- gj_tweets$text
ggplot(data=Sentimentscores_gj,aes(x=sentiment,y=Score))+geom_bar(aes(fill=sentiment),stat = "identity")+
  theme(legend.position="none")+
  xlab("Sentiments")+ylab("scores")+ggtitle("Sentiments des gens qui twittent #giletsjaunes à Paris")

Visualisation des sentiments (fréquences) Bordeaux

Nous effectuons l’analyse de sentiments cette fois dans un rayon de 100km autour de Bordeaux. Il est alors intéressant de voir les variations des scores des différents sentiments en fonction de la région.

tweets_gj <- searchTwitter("#giletsjaunes", n=1000,lang = "fr", geocode = "44.8637065,-0.6561808,100km")
gj_tweets <- twListToDF(tweets_gj)
gj_text<- gj_tweets$text
ggplot(data=Sentimentscores_gj,aes(x=sentiment,y=Score))+geom_bar(aes(fill=sentiment),stat = "identity")+
  theme(legend.position="none")+
  xlab("Sentiments")+ylab("scores")+ggtitle("Sentiments des gens qui twittent #giletsjaunes à Bordeaux")

Nuages de comparaison des mots selon le sentiment (#GiletsJaunes)

Le nuage de comparaison des mots selont le sentiments, permet de visualiser les mots qui reviennent le plus dans les Tweets exprimant chaque émotion. En effet ceci peut nous permettre de voir quels sont les thèmes associés avec chaque sentiment.

# Create comparison word cloud data

wordcloud_tweet = c(
  paste(gj_text[mysentiment_gj$anger > 0], collapse=" "),
  paste(gj_text[mysentiment_gj$anticipation > 0], collapse=" "),
  paste(gj_text[mysentiment_gj$disgust > 0], collapse=" "),
  paste(gj_text[mysentiment_gj$fear > 0], collapse=" "),
  paste(gj_text[mysentiment_gj$joy > 0], collapse=" "),
  paste(gj_text[mysentiment_gj$sadness > 0], collapse=" "),
  paste(gj_text[mysentiment_gj$surprise > 0], collapse=" "),
  paste(gj_text[mysentiment_gj$trust > 0], collapse=" ")
)

# create corpus

corpus = Corpus(VectorSource(wordcloud_tweet))
corpus = tm_map(corpus, removeWords, stopwords("french"))

# create document term matrix

tdm = TermDocumentMatrix(corpus, control = list(tolower = TRUE, stopwords = "fr"))

# convert as matrix
tdm = as.matrix(tdm)
tdmnew <- tdm[nchar(rownames(tdm)) < 11,]

# column name binding
colnames(tdm) = c('anger', 'anticipation', 'disgust', 'fear', 'joy', 'sadness', 'surprise', 'trust')
colnames(tdmnew) <- colnames(tdm)
comparison.cloud(tdmnew, random.order=FALSE,
                 colors = c("#00B2FF", "red", "#FF0099", "#6600CC", "green", "orange", "blue", "brown"),
                 title.size=1, max.words=250, scale=c(2.5, 0.4),rot.per=0.4)

On peut voir, d’un côté, que la taille des mots reflète les différents scores des sentiments qu’on a vu plus haut, et d’un autre côté on peut voir quels mots apparaissent le plus dans les tweets qui correspondent à une émotion.

Par exemple, le mot “victimes” dans les tweets reflètant le dégoût ou encore le mot “cagoule” apparaissant dans les tweets reflètant la peur.

Foulards Rouges

Nous pouvons effectuer la même étude pour le mouvement des foulards rouges.

Visualisation des sentiments (fréquences)

On peut voir, que sur les tweets contenant #foulardsrouges, nous avons differents scores pour les sentiments analysés.

tweets_fr <- searchTwitter("#foulardsrouges", n=1000,lang = "fr")
fr_tweets <- twListToDF(tweets_fr)
fr_text<- fr_tweets$text
ggplot(data=Sentimentscores_fr,aes(x=sentiment,y=Score))+geom_bar(aes(fill=sentiment),stat = "identity")+
  theme(legend.position="none")+
  xlab("Sentiments")+ylab("scores")+ggtitle("Sentiments des gens qui twittent #foulardsrouges")

Nuages de comparaison des mots selon le sentiment (#FoulardsRouges)

# Create comparison word cloud data

wordcloud_tweet = c(
  paste(fr_text[mysentiment_fr$anger > 0], collapse=" "),
  paste(fr_text[mysentiment_fr$anticipation > 0], collapse=" "),
  paste(fr_text[mysentiment_fr$disgust > 0], collapse=" "),
  paste(fr_text[mysentiment_fr$fear > 0], collapse=" "),
  paste(fr_text[mysentiment_fr$joy > 0], collapse=" "),
  paste(fr_text[mysentiment_fr$sadness > 0], collapse=" "),
  paste(fr_text[mysentiment_fr$surprise > 0], collapse=" "),
  paste(fr_text[mysentiment_fr$trust > 0], collapse=" ")
)

# create corpus

corpus = Corpus(VectorSource(wordcloud_tweet))
corpus = tm_map(corpus, removeWords, stopwords("french"))

# create document term matrix

tdm = TermDocumentMatrix(corpus, control = list(tolower = TRUE, stopwords = "fr"))

# convert as matrix
tdm = as.matrix(tdm)
tdmnew <- tdm[nchar(rownames(tdm)) < 11,]

# column name binding
colnames(tdm) = c('anger', 'anticipation', 'disgust', 'fear', 'joy', 'sadness', 'surprise', 'trust')
colnames(tdmnew) <- colnames(tdm)
comparison.cloud(tdmnew, random.order=FALSE,
                 colors = c("#00B2FF", "red", "#FF0099", "#6600CC", "green", "orange", "blue", "brown"),
                 title.size=1, max.words=250, scale=c(2.5, 0.4),rot.per=0.4)

Géolocalisation des Tweets

La géolocalisation des tweets peut être un outil particulièrement efficace pour pouvoir situés les communauté qui sont les plus actives sur Twitter, en l’occurence les communauté qui s’exprime le plus sur un sujet particulier. Il était possible auparavant de récuperer les coordonées géographiques de l’émeteur du tweet, ce qui a naturèlment été considéré, entre autres, comme une atteinte à la vie privée des utilisateurs de Twitter.

Il éxiste cependant une méthode pour pouvoir géolocalisé les tweets, cette fois en utilisant la localisation indiquées par l’utilisateurs de Twitter sur son profil.

Cette méthode a nécéssité la familiarisation avec l’outil google

Packages nécessaires pour effectuer la géolocalisation

library(rtweet)
library(ggplot2)
library(ggmap)
library(data.table)
library(maps)
library(stringr)

source("https://raw.githubusercontent.com/dkahle/ggmap/897267760fb28550913f6a8435e18bb8c82c639e/R/helpers.R")
#Install / load "RJSONIO" package:
if (!require("RJSONIO")) {
  install.packages("RJSONIO", repos="http://cran.rstudio.com/") 
  library("RJSONIO")
}

#Install key package helpers:
source("https://raw.githubusercontent.com/LucasPuente/geocoding/master/geocode_helpers.R")

#Install modified version of the geocode function
#(that now includes the api_key parameter):
source("https://raw.githubusercontent.com/LucasPuente/geocoding/master/modified_geocode.R")

ipak <- function(pkg){
  new.pkg <- pkg[!(pkg %in% installed.packages()[, "Package"])]
  if (length(new.pkg)) 
    install.packages(new.pkg, dependencies = TRUE)
  sapply(pkg, require, character.only = TRUE)
}
packages <- c("maps", "mapproj", "splancs")
ipak(packages)
##    maps mapproj splancs 
##    TRUE    TRUE    TRUE

Récupération des tweets

Depuis quelques années il n’est plus possible d’acceder au coordonnées géographiques de l’emetteur d’un tweet. Aisin nous allons proceder differemment dans la partie ci dessous :

Cette fois ci nous utilisons le package “rtweet”, qui permet de récuperer, entre autres, la localisation entrée par l’utilisateur de chaque compte twitter.

Récupération des tweets #giletsjaunes

gj_tweets<- search_tweets(q = "#giletsjaunes", n = 10000, lang = "fr", include_rts = FALSE, geocode = "47.07,2.36,1000km")

Filtrage des lieux d’emission des tweets

# Nous filtrons les tweets dont l'emetteur n'a indiqué aucune localisation
gj_tweets<-subset(gj_tweets, location != "")

# Nous filtrons les tweets dont l'emetteur a indiquée une localisation qui n'est pas en France (ou un lieu imaginaire)
location_clean<-str_subset(gj_tweets$location, ", France")
location_index<-str_which(gj_tweets$location, ", France")
gj_tweets<-gj_tweets[location_index,]

Nécessité d’utiliser le service Google Cloud Platform

Pour pouvoir convertir la localisation du tweet en coordonnées géographiques, nous avons besoin d’APIs Google.

On génère une fonction qui récupère les coordonnées de chaque ville à l’aide des APIs Google Geocoding :

geocode_apply<-function(x){
  geocode(x, source = "google", output = "all", api_key="**********code API secret***********")
}

On applique la fonction :

geocode_results_final_gilets_jaunes<-sapply(gj_tweets$location, geocode_apply, simplify = F)
geocode_results <- geocode_results_final_gilets_jaunes

On nettoie les résultats du geocoding :

# On ne garde que les géolocalisation bien trouvées (status = "ok")

condition_a <- sapply(geocode_results, function(x) x["status"]=="OK")
geocode_results1<-geocode_results[condition_a]

# On ne garde que les géolocalistions auquelles ne correspond qu'un seul et unique résultat

condition_b <- lapply(geocode_results, lapply, length)
condition_b2<-sapply(condition_b, function(x) x["results"]=="1")
geocode_results<-geocode_results1[condition_b2]

Nous allons mettre en forme les géolocalisation afin de les illustrées sur une carte :

source("https://raw.githubusercontent.com/LucasPuente/geocoding/master/cleaning_geocoded_results.R")


# Conversion en tableaux :
results_b<-lapply(geocode_results, as.data.frame)
results_c<-lapply(results_b,function(x) subset(x, select=c("results.formatted_address", "results.geometry.location")))
# Formattage des data.frame :
results_d<-lapply(results_c,function(x) data.frame(Location=x[1,"results.formatted_address"],
                                                   lat=x[1,"results.geometry.location"],
                                                   lng=x[2,"results.geometry.location"]))


# Concaténation des tableaux :
results_e<-rbindlist(results_d)

# On rajoute les localisation entrées par les utilisateurs :
results_f<-results_e[,Original_Location:=names(results_d)]


# On ne garde que les résultats en France :
french_results_gj<-subset(results_f,
                         grepl(", France", results_f$Location)==TRUE)

Voici la forme du tableau final qui va nous servire à géolocaliser les utilisateurs de twitter en France :

Avec en dessous la forme originale des données entrées par les utilisateurs

head(french_results_gj)
##                        Location      lat      lng            Original_Location
## 1:                Paris, France 48.85661 2.352222                Paris, France
## 2:                Paris, France 48.85661 2.352222                Paris, France
## 3:                Paris, France 48.85661 2.352222                Paris, France
## 4:                Paris, France 48.85661 2.352222                Paris, France
## 5:       60000 Beauvais, France 49.42954 2.080712   Beauvais, Picardie, France
## 6: Boulogne-Billancourt, France 48.83970 2.239912 Boulogne-Billancourt, France

Nous allons projeter sur une carte les utilisateurs de Twitter qui ont tweeté un #giletsjaunes, en effet toute la démarche ci dessus a non seulement permis de récuperer les lieux de provenance des tweets, de les filtrer, mais aussi de convertir ces lieux en coordonnées géographiques grâce à Google Cloud Platform et en l’occurence l’API Geocoding de ce service.

Géolocalisation des tweets #giletsjaunes

#Generate a blank map:
albers_proj<-map("france", proj="albers", param=c(20, 45), col="#999999", fill=TRUE, bg=NA, lwd=0.2, add=TRUE, resolution=1)
map(albers_proj)
albers_proj<-map("france", proj="albers", param=c(20, 45), col="#999999", fill=TRUE, bg=NA, lwd=0.2, add=TRUE, resolution=1)
#Add points to it:
points(mapproject(french_results_gj$lng, french_results_gj$lat), col="yellow", bg="#00000030", pch=21, cex=2.0)
#Add a title:
mtext("La géolocalisation des tweets #giletsjaunes", side = 3, line = -3.5, outer = T, cex=1.5, font=3)

Géolocalisation des tweets #foulardsrouges

Nous procédons de la même manière pour les tweets #foulardsrouges

Conclusion

Le mouvement des gilets jaunes occupe l’actualité depuis quelques mois, en effet le mouvement a commencé le 17 novembre 2018. Avec une grande quantité de posts et de tweets sur les réseaux sociaux qui traitent de ce thème, le contenu de ces posts peut paraître trop vaste pour pouvoir être assimilé. Nous avons ainsi vu grâce à différentes fonctions dans ce projet, qu’il est ainsi possible, non seulement de récupérer ces tweets et ces posts, mais aussi de les interpréter et faire ressortir les points d’accord et de désaccord entre les différents parties politiques et les gilets jaunes. Avec certains résultats très intéressant, comme par exemple une ressemblance dans le lexique utilisé par les partis d’extrêmes droites et gauches et les gilets jaunes. On a été confronté à certaines difficultés non seulement du fait de l’actualité du sujet mais aussi de l’évolution constante des termes et conditions d’utilisations de Twitter et des APIs permettant de récuperer les données disponibles. Cette étude peut être plus approfondie, et les outils utilisés peuvent être appliqués à différents thème et à des fins toute aussi diverses.