Introduction

Twitter est un réseau social populaire qui a été créé le 21 mars 2006 où les utilisateurs peuvent partager de courts messages de type SMS appelés tweets. Les hommes politiques, les sportifs l’utilisent pour donner la primeur de leur actualité, leurs décisions, leurs actions à venir, les journalistes commentent les événements en direct, les entreprises font la promotions des produits et interagissent avec les clients. Au 5 mars 2017, Twitter comptait 313 millions d’utilisateurs actifs par mois avec 500 millions de tweets envoyés par jour et était disponible en plus de 40 langues.

L’analyse des tweets s’inscrit dans le cadre de l’analyse textuelle (text mining), chaque document est un texte rédigé. Afin d’effectuer ce projet Open Data, nous commençons d’abord par une analyse statistique descriptive.

Le package twitteR nous permet d’accéder aux données du site Twitter : [https://twitter.com]. Ces données sont constituées de mots et de phrases déposées quotidiennement par des millions d’utilisateurs dans le monde, ainsi que de méta-données sur les utilisateurs de ce réseau social.

Il faut au préalable disposer soi-même d’un compte Twitter et créer une application Twitter [https://apps.twitter.com] qui nous permettra d’effectuer des analyses en connectant notre console R à Twitter en utilisant l’API Twitter.

setup_twitter_oauth(consumer_key, consumer_secret, access_token,access_secret)
## [1] "Using direct authentication"

1. Analyse textuelle

Dans un premier temps, nous nous concentrons sur les tweets qui traitent de l’annonce du mariage du prince Harry et de sa financée Meghan Markle.
Nous allons étudier les auteurs et le contenu de ces tweets.
La fonction searchTwitter permet de charger des tweets qui contiennent le mot clé “prince Harry Meghan”. On limite le nombre de messages extraits à 500.

tweets_prince = searchTwitter("prince Harry Meghan", lang="en", since='2017-11-27', n=500)

1.1 Analyse des auteurs de tweets

Nous pouvons établir une liste des 10 auteurs les plus actifs avec le nombre de messages envoyés.

#comptage du nombre de message par auteurs
comptage <- table(tweets.df$screenName)
#tri décroissant
comptage <- sort(comptage,decreasing=TRUE) 
#10 premiers auteurs les plus actifs
print(comptage[1:10])
## 
##  Daily_Express  MizpahJohnson       ReportUK   TheTruth24UK      Tooo_Know 
##              8              6              6              6              6 
##  Wedding_Agent       cbc_diff sliaisonmonick       ToooKnow azheykhunweper 
##              6              4              4              4              3

Nous pouvons identifier les pseudo des auteurs ayant envoyé 4 messages ou plus.

print(length(unique(tweets.df$screenName)))
## [1] 406
barplot(comptage [comptage >= 4], las = 2,cex.names=0.7, col="darkolivegreen4")

Finalement, la concentration des auteurs est assez forte. Par rapport au nombre de messages (n=500), le nombre unique d’auteurs l’est également (406) et Daily_Express est le premier auteur qui envoie plus de messages.

Les auteurs de messages originaux

Ce premier classement donne un premier point de vue sur l’activité des auteurs. Mais il peut être biaisé par le fait que certains messages sont en réalité de simples retweets. Pour identifier les auteurs de messages “originaux”, qui amènent une réelle valeur ajoutée dans les échanges, nous essayons d’isoler les messages qui ne sont pas des retweets, puis nous comptabilisons de nouveau les auteurs.

Nous identifions tout d’abord les messages qui ne sont pas des retweets.

#liste des messages originaux
id_originaux <- which(!tweets.df$isRetweet)
#nombre de messages originaux
print(length(id_originaux))
## [1] 318
#Ils sont au nombre 291 (sur les 500 messages initiaux).

#comptage du nombre de message par auteurs
comptage_bis <- table(tweets.df$screenName[id_originaux]) #tri décroissant
comptage_bis <- sort(comptage_bis,decreasing=TRUE)
#graphique de ceux qui ont plus de 4 (inclus) messages
barplot(comptage_bis [comptage_bis >= 4], las = 2,cex.names=0.7, col = "lightgoldenrod3")

Les auteurs ayant rédigé 4 messages originaux ou plus sont plus rares (5), alors qu’ils étaient 9 si l’on comptabilisait les retweets. Certains, apparemment très actifs, ont disparu de la circulation.

1.2 Analyse de la popularité à travers les retweets:

Les internautes retweetent les messages lorsqu’ils en ont apprécié la teneur. Parmi les messages qui sont des retweets, nous essayerons d’isoler les 2 messages qui sont les plus populaires.

##        screenName           id retweetCount
## 90 stydiagissette 9.585896e+17       116108
## 92      flukez123 9.585881e+17       116108
## [1] RT @BarackObama: Michelle and I are delighted to congratulate Prince Harry and Meghan Markle on their engagement. We wish you a lifetime of…
## [2] RT @BarackObama: Michelle and I are delighted to congratulate Prince Harry and Meghan Markle on their engagement. We wish you a lifetime of…
## 404 Levels: .@NaughtyNiceRob: Kylie Jenner wants that epidural; Meghan Markle &amp; Prince Harry will replace Will &amp; Kate at Common… https://t.co/blAc6sx0Gk ...

Nous avons 2 messages avec des auteurs et des identifiants distincts qui sont répétés chacun 116108 fois et qui correspondent au même texte. On se rend qu’il s’agit du même message que les internautes aiment marteler visiblement. Donc, il nous faut enlever les messages en doublon. Nous nous servons de la fonction duplicated() qui permet de les identifier.

## [1] RT @BarackObama: Michelle and I are delighted to congratulate Prince Harry and Meghan Markle on their engagement. We wish you a lifetime of…
## [2] RT @ClarenceHouse: The Prince of Wales is delighted to announce the engagement of Prince Harry to Ms. Meghan Markle. https://t.co/zdaHR4mcY6
## 404 Levels: .@NaughtyNiceRob: Kylie Jenner wants that epidural; Meghan Markle &amp; Prince Harry will replace Will &amp; Kate at Common… https://t.co/blAc6sx0Gk ...
## [1] 116108  32987

Nous avons bien deux messages distincts maintenant, qui sont répétés respectivement 116108 et 32987 fois.

Nous pouvons aussi représenter le nombre d’occurrence de 15 premiers tweets avec leur ID.

Ou encore afficher l’histogramme des fréquences du nombre de retweets.

1.3 Analyse des thèmes et des individus

Nous souhaitons dans un premier temps analyser les références aux thèmes (#) et aux auteurs (@) qui apparaissent dans les messages.
Un premier nettoyage est nécessaire pour éliminer les éléments qui peuvent engendrer du bruit et des doublons, puisqu’il y a souvent des répétitions dans les messages, ensuite on retire les sauts de ligne, les URL, les espaces en trop et les accents.

1.3.1 Nettoyage des tweets.

# éliminer les doublons
dfUnique <- tweets.df[!duplicated(tweets.df$text),]
print(nrow(dfUnique))
messages <- dfUnique$text
print(length(messages))
print(messages[22])

msgClean <- gsub("\n"," ",messages) 
msgClean <- gsub('http\\S+\\s*',"",msgClean) 
msgClean <- gsub("\\s+"," ",msgClean) 
msgClean <- gsub("[\\]","",msgClean)
msgClean <- gsub("\\s*$","",msgClean)
#msgClean <- tolower(msgClean)
msgClean <- gsub("[éèê]","e",msgClean) 
msgClean <- gsub("[àâ]","a",msgClean) 
msgClean <- gsub("[ùû]","u",msgClean)
msgClean <-gsub("rt ", "", msgClean)
msgClean <-msgClean[!duplicated(msgClean)]
print(length(msgClean))

1.3.2 Analyse des individus via leur pseudo

Les auteurs sont identifiés par le caractère “@” (screenname). Ils apparaissent dans les messages parce qu’ils sont retweetés, ou parce qu’ils sont cités nommément. Dans ce qui suit, nous allons les comptabiliser. On peut trouver les 10 individus les plus fréquents.

## liste_individus
##        @YouTube       @ReportUK    @Independent  @ClarenceHouse 
##              10               6               4               3 
##  @Daily_Express         @ELLEUK       @BazaarUK @Bridesmagazine 
##               3               3               2               2 
## @Celebrity_VIP1   @ELLEmagazine 
##               2               2

1.3.3 Analyse des thèrmes

Après avoir agrégé les textes de tous les individus, nous convertissons cette liste en corpus qui contient 500 documents (un document par individu), puis appliquons la fonction TermDocumentMatrix qui permet de compter les occurrences de chaque mot en prenant soin d’enlever les stopwords (les stopwords sont des mots très courants dans les phrases et vides de sens tels que les articles ou encore les prépositions).

# construire la matrice des fréquences:
# On compte le nombre d'occurrences par mots
dtm = TermDocumentMatrix(corpus, control = list(tolower = TRUE, stopwords = word))
dtm.matrix = as.matrix(dtm)
v <- sort(rowSums(dtm.matrix), decreasing = TRUE)
d <- data.frame(word = names(v), freq = v)
barplot(d[1:25,]$freq, las = 2, names.arg = d[1:25,]$word,
        col ="lightblue", main ="Mots les plus fréquents",
        ylab = "Fréquences")

1.3.4 Analyse des hashtags.

Le hashtag appelé mot-clic ou mot dièse en français permet de transformer en lien cliquable un sujet de discussion. En d’autres mots, le hashtag permet de catégoriser des sujets en un seul clic. Par exemple, vous assistez à un événement, une conférence ou un congrès et vous commentez l’événement sur Twitter en utilisant le hashtag de l’événement. Les gens qui y assistent échangent sur le sujet pendant que se déroule l’événement et les absents, grâce à votre lien hashtag, peuvent connaître le nom des gagnants et voir des photos en direct.

Nous obtenons un graphe avec la fréquence des hashtags en ordre décroissant. Les hashtags les plus utlisées par les utilisateurs sont “Endeavour awards”, “Meghan Markle” et “prince Harry”.

1.4 Analyse des Sentiments.

L’analyse de sentiments est une branche de l’analyse textuelle qui essaye de définir les opinions, sentiments et attitudes présentes dans un texte. Nous utilisons ** NRC Emotion Lexicon** qui est un lexique de mots et de leurs associations avec huit émotions (colère, peur, anticipation, confiance, surprise, tristesse, joie et dégoût) et deux sentiments (négatifs et positifs). Tous les lexiques incluant des entrées pour des mots anglais peuvent être utilisés pour analyser des textes anglais, des traductions automatiques des entrées du lexique de l’association de mots sont disponibles dans 40 autres langues, y compris le français, l’arabe, le chinois et l’espagnol.

##  [1] "peur"         "anticipation" "surprise"     "positif"     
##  [5] "tristesse"    "colère"       "négatif"      "dégoût"      
##  [9] "joie"         "confiance"

Les tweets concernant l’annonce du mariage de prince Harry et sa fiancée Meghan Markle sont majoritairement positifs.

2. Classification

Maintenant nous allons effectuer une Classification Ascendante Hiérarchique afin d’observer si nous pouvons faire des regroupements en classes. Pour ce faire, nous récupérons toujours 1000 tweets mentionnant le prince Harry et sa fiancée.

Le dendrogramme au-dessus met en évidence un regroupement en k = 5 classes. Nous observons que ce regroupement est plutôt cohérent :

  • Les mots “harry”, “prince”, “meghan”, “markle” sont regroupés.
  • Les mots “achievements”, “attending”, “thursday”, “awards”, “celebrating”, “endeavourg” sont regroupés. En effet, le couple ont participé à l’Endeavour Fund Awards à Londres qui a eu lieu au Goldsmiths Hall jeudi 1er février 2018.
  • Les mots “royal”, “wedding” apparaissent ensemble.

3. Géolocalisation

Ensuite, nous allons utiliser les tweets mentionnant #Metoo pour créer une cartographie interactive avec la fonction leaflet() qui permet de réaliser des cartes dynamiques tout en codant en R. Sur cette carte, nous pouvons localiser les membres qui ont utilisé le hashtag #Metoo et il est possible de zoomer et de se déplacer sur la carte, les cercles sont cliquables.

#------------------------#
# Visualization: leaflet #
#------------------------#

# Set colours
pal <- colorNumeric(palette = c("#ffe6e6", "#ff8080", "#ff0000"), domain = c(0, 100))

# Plot user locations with color of locations reflecting number of followers
leaflet(userFrame_final, width = "100%") %>%
  addProviderTiles("CartoDB.DarkMatter") %>%
  addCircleMarkers(~lng,
                   ~lat,
                   color = ~pal(followersCount),
                   radius = 1.5)
#------------------------#
# Visualization: ggplot2 #
#------------------------#

# Download, unzip and import shapefiles from Natural Earth webpage
#temp <- tempfile()
#download.file("http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/50m/cultural/ne_50m_admin_0_countries.zip", temp, mode = "w")
#unzip(temp)


world_shp <- readShapeSpatial("ne_50m_admin_0_countries.shp", proj4string = CRS("+proj=longlat +ellps=WGS84"))
#unlink(temp)

# Remove Antarctica
world_shp <- subset(world_shp, NAME != "Antarctica")

# Plot user locations
ggplot() +
  geom_polygon(data = world_shp, aes(x = long, y = lat, group = group)) +
  geom_point(data = userFrame_final, aes(x = lng, y = lat), size = 1.2, color = "red") +
  labs(x = "", y = "") +
  theme(axis.text.x = element_blank(), axis.text.y = element_blank(), axis.ticks = element_blank(),
        panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.background = element_blank()) +
  coord_equal()

Sur la carte, chaque point rouge représente un tweet, nous observons que les États-Unis comptent le plus de tweets, suivi par l’Europe.

4. Prédiction de parti politique

On souhaite prédire l’appartenance politique d’un utilisateur de Twitter à un parti grâce à l’analyse de ses tweets et plus précisément grâce à l’analyse de la fréquence des mots qu’il utilise. Nous allons considérer les 4 grands partis français : la France insoumise, la République en marche, les Républicains et le Front national.

4.1 Données d’apprentissage

Nous récupérons tout d’abord les tweets (et les retweets) effectués par les comptes Twitter des partis et des personnes suivants :

la France insousmise la République en marche les Républicains le Front national
Compte officiel de la France insoumise Compte officiel de la République en marche Compte officiel des Républicains Compte officiel du Front national
Jean-Luc Mélenchon Emmanuel Macron Laurent Wauquiez Marine LePen
Alexis Corbière Edouard Philippe Alain Juppé Florian Philippot
Eric Coquerel Christophe Castaner Valérie Pécresse Steeve Briois
François Ruffin Mounir Mahjoubi Valérie Boyer Gilbert Collard

Comme la fréquence des mots des tweets peuvent être différents d’une actualité à une autre, nous ne retenons que les tweets d’une période assez courte. Ici nous conservons les tweets effectués entre le 1 novembre 2017 et le 1 février 2018.

Nettoyer les textes.

Nous décidons d’enlever les accents des mots (“donné” est transformé en “donne”), de supprimer les “RT”, les “@”, les hashtags, la ponctuation, les nombres et les espaces en trop.

FI.clean <- clean.text(FI.df$text)
Jean.clean <- clean.text(Jean.df$text)
Francois.clean <- clean.text(Francois.df$text)
Alexis.clean <- clean.text(Alexis.df$text)
Eric.clean <- clean.text(Eric.df$text)


EM.clean <- clean.text(EM.df$text)
Emmanuel.clean <- clean.text(Emmanuel.df$text)
Edouard.clean <- clean.text(Edouard.df$text)
Christophe.clean <- clean.text(Christophe.df$text)
Mounir.clean <- clean.text(Mounir.df$text)


LR.clean <- clean.text(LR.df$text)
Laurent.clean <- clean.text(Laurent.df$text)
Alain.clean <- clean.text(Alain.df$text)
Valerie_P.clean <- clean.text(Valerie_P.df$text)
Valerie_B.clean <- clean.text(Valerie_B.df$text)


FN.clean <- clean.text(FN.df$text)
Marine.clean <- clean.text(Marine.df$text)
Florian.clean <- clean.text(Florian.df$text)
Steeve.clean <- clean.text(Steeve.df$text)
Gilbert.clean <- clean.text(Gilbert.df$text)

Nous concaténons ensuite les tweets des membres d’un même parti.

FI.all <-c(FI.clean, Jean.clean,Francois.clean,Alexis.clean,Eric.clean)
length(FI.all)

EM.all <- c(EM.clean,Emmanuel.clean,Edouard.clean,Christophe.clean,
Mounir.clean)

LR.all <- c(LR.clean, Laurent.clean, Alain.clean, Valerie_P.clean, Valerie_B.clean )

FN.all <- c(FN.clean, Marine.clean, Florian.clean, Steeve.clean, Gilbert.clean)

Touslestext <- c(FI.all, EM.all, LR.all, FN.all)
length(FI.all)
length(EM.all)
length(LR.all)
length(FN.all)
length(Touslestext)

Ensuite nous faisons un découpage de chaque concaténation de tweets en 10 groupes afin d’obtenir plus d’observations.

# Couper la liste des tweets de chaque parti en n sous-listes aléatoirement
n=10
FISplit<- split(FI.all, sample(rep(1:n, length.out = length(FI.all))))
EMSplit<- split(EM.all, sample(rep(1:n, length.out = length(EM.all))))
LRSplit <- split(LR.all, sample(rep(1:n, length.out = length(LR.all))))
FNSplit <- split(FN.all, sample(rep(1:n, length.out = length(FN.all))))
length(FISplit)
#FISplit[1]

Les tweets de chaque groupe sont ensuite agrégés.

# Aggréger les tweets d'un même groupe de tweets
FIGroup <- lapply(FISplit , function(x) paste(x, collapse = " "))
EMGroup <- lapply(EMSplit , function(x) paste(x, collapse = " "))
LRGroup <- lapply(LRSplit , function(x) paste(x, collapse = " "))
FNGroup <- lapply(FNSplit , function(x) paste(x, collapse = " "))

all <- c(FIGroup, EMGroup, LRGroup, FNGroup)
FIGroup[1]
length(FIGroup)  #10
length(all)   # 40

save(all, file="all_tweet_prediction.RData")

Nous construisons ensuite le corpus de mots en supprimant les mots très courants de la langue française et vides de sens tels que les articles ou encore les prépositions. Nous obtenons ensuite une matrice, les lignes sont les groupes de tweets et les colonnes le nombre d’occurrences pour chaque mot. 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é.

n=10
# Créer la matrice de fréquence de mots
dtm <- DocumentTermMatrix(corpus)
#inspect(dtm)
m <- as.matrix(dtm)

nbr_rowMots <- apply(m,1,sum)
tableFreq <- sweep(m,1,nbr_rowMots,"/")
#tableFreq[1:6,1:8]
dim(tableFreq)
# Vérifier si les sommes de toutes les lignes sont 1
#rowSums(tableFreq)

parti <- as.factor(c(rep("FI",n),rep("EM",n), rep("LR",n), rep("FN",n)))
length(parti)

tableLabel = data.frame(parti, tableFreq)
tableLabel[1:6,1:8]
matrice des occurrences des mots
abord abusif accentue acceptable accepte acces accompagne accompagnee accord accorder
3 2 1 1 1 1 1 1 1 1
2 0 0 0 0 0 0 0 3 0
2 0 0 0 1 0 1 0 3 0
2 0 0 0 0 1 0 0 2 0
2 1 0 0 0 1 0 0 3 0
0 1 0 0 0 2 0 0 0 0
0 0 0 0 0 3 1 0 1 0
1 1 0 0 0 1 0 0 0 0
1 0 0 0 1 0 0 0 1 0
3 0 0 0 0 0 0 0 2 0

4.2 1ère ACP

Afin de visualiser l’appartenance en 4 classes distinctes, nous faisons une analyse en composantes principales du tableau de données.

library(FactoMineR) 
res <- PCA(as.data.frame(tableLabel), quali.sup=1, graph=FALSE, scale.unit = TRUE, ncp = 10) # original data in input
par(mfrow= c(1,3))
plot(res,choix="ind", axes = c(1,2), cex=1.5,title="", habillage = 1, label="none", invisible = "quali")
plot(res,choix="ind", axes = c(1,3), cex=1.5,title="", habillage = 1,label="none")
plot(res,choix="ind", axes = c(2,3), cex=1.5,title="", habillage = 1, label="none")

Sur les 3 premiers plans factoriels, on constate bien une séparation en 4 classes disjointes.

4.3 Réduction de variables par forêt aléatoire

Pour réduire le nombre de varibale, nous effectuons le classifieur forêt aléatoire en regardant la variable importance et choisissons 300 mots les plus importants pour chaque partie politique, puis nous ne gardons que des mots en commun, cela nous permt de passer de 10973 mots à 648.

rf_all <- randomForest(parti ~., data = tableLabel, importance = TRUE)
save(rf_all, file="rf_all.RData")
rfImp <- rf_all$importance
rfImpEM <-rfImp[, 1]
rfImpFI <-rfImp[, 2]
rfImpFN <-rfImp[, 3]
rfImpLR <-rfImp[, 4]


rfImpSortEM <- sort(rfImpEM, decreasing=TRUE, index.return=TRUE)
rfImpSortFI <- sort(rfImpFI, decreasing=TRUE, index.return=TRUE)
rfImpSortFN <- sort(rfImpFN, decreasing=TRUE, index.return=TRUE)
rfImpSortLR <- sort(rfImpLR, decreasing=TRUE, index.return=TRUE)

nMots=300
#print(names(rfImpSortEM$x[1:nMots]))
# Prendre la réuninon des mots les plus importants pour chaque parti
nomVar = c(names(rfImpSortEM$x[1:nMots]),names(rfImpSortFI$x[1:nMots]), names(rfImpSortFN$x[1:nMots]), names(rfImpSortLR$x[1:nMots]) )
nomVar <-unique(nomVar)
#nomVar
length(nomVar)

4.4 2ème ACP

Pour vérifier si chaque parti politique est séparé des autres sur les trois premiers plans factoriels après la réduction du nombre de variables, nous effectuons une seconde ACP.

tableFreq2 <- tableLabel[, which(names(tableLabel) %in% nomVar)]
dim(tableFreq2)   
## [1]  40 659
#colSums(tableFreq2)
tableLabel2 <- data.frame(parti, tableFreq2)
#tableLabel2[1:6,1:8]


res2 <- PCA(as.data.frame(tableLabel2), quali.sup=1, graph=FALSE, scale.unit = TRUE, ncp = 10) # original data in input
par(mfrow= c(1,3))
plot(res2,choix="ind", axes = c(1,2), cex=1.5,title="", habillage = 1, label="none")
plot(res2,choix="ind", axes = c(1,3), cex=1.5,title="", habillage = 1,label="none")
plot(res2,choix="ind", axes = c(2,3), cex=1.5,title="", habillage = 1, label="none")

Il est évident que chaque groupe est bien séparé, nous allons donc ensuite construire une forêt aléatoire avec seulement les mots sélectionnés.

dim(tableLabel)
x = tableLabel[, which(names(tableLabel) %in% nomVar) ]
dim(x)
#names(x)
# Réordonner les colonnes
#x = x[, c(nomVar, setdiff(colnames(x), nomVar))] 
#colnames(x)
rf1 <- randomForest(x =x,  y = tableLabel[, which(names(tableLabel) %in% "parti") ], importance = TRUE)
rf1

4.5 Données de test

Pour créer la table de données de test, nous récupérons les 40 tweets des comptes suivants et les nettoyer comme pour les comptes d’apprentissage:

la France insoumise la République en marche les Républicains le Front national
Loïc Prudhomme François de Rugy Nicolas Sarkozy Louis Aliot
Caroline FIAT Cédric Villani Jean-François Nicolas BayVerified
Michel Larive Bruno Le Maire Eric Ciotti Bruno Bilde
Bastien Lachaud Gérard Collomb Damien Abad Sébastien ChenuVerified
Adrien Quatennens Gérald DARMANIN Julien Aubert Ludovic PAJOT

4.6 Prédiction

ntweet=1500
data.test <- data.frame()
noms_classif <- nomVar

for( user in all.test$pseudo) {
  print(user)
    # On récupère 200 tweets pour être sûr d'en avoir au moins 100 qui ne sont pas des RT
    tweets = userTimeline(user, n=ntweet, includeRts = TRUE)
    # On récupère le texte des tweets
    some_txt = sapply(tweets,function(x) x$getText())
    # On nettoie les tweets                                    
    some_txt = clean.text(some_txt)
    p=length(some_txt)
    # On garde les p premiers tweets
    some_txt = some_txt[1:p]
    # On les colle ensemble pour n'avoir qu'un groupe
    some_txt = paste(some_txt,collapse=" ")
    
    # On supprime les stop words et on génère la table des fréquences
    some_txt = removeWords(some_txt,stopwords("french"))
    
    corpus = Corpus(VectorSource(some_txt))
    tdm = TermDocumentMatrix(corpus)
    tdm = as.matrix(tdm)
    noms = row.names(tdm)
    tdm = as.data.frame(t(tdm))
    nbr_ColMots <- apply(as.matrix(tdm),1,sum)
    tableFreq <- sweep(tdm,1,nbr_ColMots,"/")
    tdm = tableFreq
    
    # On crée la matrice ne contenant que les mots utilisés dans la classification
    tmp = c()
    for (i in noms_classif){
      ind = which(noms==i)
      if (length(ind)==0){
        tmp = cbind(tmp,rep(0,length(tdm[,1])))
      }
      else
        tmp = cbind(tmp,tdm[,ind])
    }
    names(tmp) = noms_classif
    tmp <- data.frame(as.list(tmp))
    tdm = tmp
    print(tdm[,1:5])
    data.test <- rbind(data.test, tdm)
}
data.test <- data.frame(all.test, data.test)
save(data.test, file="datatest.RData")
load("datatest.RData")
pred = predict(rf1,newdata=data.test[, -c(1,2)])
erreur <- sum(pred!=data.test[, 2])/length(data.test[, 2])
erreur

La prédiction par forêt aléatoire nous donne un taux d’erreur 5%.

Conclusion

Nous avons vu qu’il est possible de prédire l’appartenance politique d’un compte Twitter avec une bonne précision si l’utilisateur est un membre d’un parti. Si le compte n’est pas celui d’une personne politique, la précision est moins bonne. Ceci est dû au fait que nous n’avons pris que des comptes d’hommes et de femmes politiques pour l’ensemble d’apprentissage.
De plus, notre façon d’obtenir les données d’apprentissage n’est pas très automatique, puisque l’on rentre manuellement un compte et son parti associé.
Notre analyse textuelle ne prend pas en compte les mots dans leur contexte et leur sens. Il serait intéressant de prendre en compte le moment où le tweet a été fait. De plus, au lieu de se limiter à l’analyse des mots des tweets on pourrait penser à l’avenir à considérer la liste des abonnements qu’un utilisateur possède.