R et Twitter
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
On va dans ce post, illustrer une utilisation simple des packages twitteR, StreamR, tm qui permettent faire du textmining. En réalité, les deux premiers permettent de récuperer les tweets et de faire des comptages simples et complexes et le dernier permet de faire du textmining; On reviendra plus en détail sur ce dernier dans un prochain billet.
Analyse simple – Twitter :comment récupérer les tweets?
Il est un peu difficile (avec la dernière api de Tweeter) de se connecter pour récupérer les tweets.
Il faut en réalité se connecter avec un compte twitter de développeur à créer sur le site api.twitter.com
Voici le code à adapter pour indiquer à votre ordinateur connecté à votre réseau, comment se connecter sur votre compte développeur.
Les codes consumerKey et consumersecret sont donnés par tweeter et sont personnels.
# download.file(url='http://curl.haxx.se/ca/cacert.pem', # destfile='cacert.pem') requestURL <- # 'https://api.twitter.com/oauth/request_token' authURL = # 'http://api.twitter.com/oauth/authorize' accessURL= # 'http://api.twitter.com/oauth/access_token' consumerKey =xxxxxx # consumerSecret =xxxxxxxx myacc <- # OAuthFactory$new(consumerKey=consumerKey, consumerSecret=consumerSecret, # requestURL=requestURL, accessURL=accessURL, authURL=authURL) # myacc$handshake(cainfo = paste0( temp dir() , #'/cacert.pem' ) , ssl.verifypeer = FALSE ) # myacc$handshake() registerTwitterOAuth(myacc)
Une fois enrégistré et sauvegardé, on n'a plus besoin dans une autre session R de recommencer la manipulation.
setwd("D:\\PERSO\\Tutoriels\\TwitteR") load("twitter.Rdata") registerTwitterOAuth(myacc) # Récupérer 500 tweets les plus récents de la manif pour # tous depuis le mois de septembre 2012 manif <- searchTwitter("#lamanifpourtous", n = 500, since = "2012-09-01", cainfo = "cacert.pem") # C'est une liste qui est créée. On peut récupérer les # résultats dans un dataframe # manif.df<-twListToDF(twList=manif) Ou encore de manière # plus élégante. Pour ceux qui n'ont pas encore pratiqué R, # cette fonction est très utile dans toutes circonstances. manif.df <- do.call("rbind", lapply(manif, as.data.frame)) # Le dataframe créé comprend plusieurs variables. On y # reviendra par la suite. Mais pour accéder au texte head(manif.df$text) ## [1] "RT @FranceOFrancais: Un véritable Mensonge d'Etat : #Valls trafique les vidéos de la #ManifPourTous \n#lamanifpourtous \nhttps://t.co/z9AOPYS…" ## [2] "RT @ALC_officiel: #MensongedEtat : #Valls trafique les vidéos de la #ManifPourTous \n#PSmenteur \n#OnLacheRien \n#lamanifpourtous \nhttps://t.c…" ## [3] "C'est impressionnant de voir le nbr de néonazis qui soutiennent la cause de la #LaManifPourTous 0_0 @christineboutin @Frigidebarjot" ## [4] "@itele un heterophobe ! #MariagaPourTous #lamanifpourtous" ## [5] "RT @FranceOFrancais: Un véritable Mensonge d'Etat : #Valls trafique les vidéos de la #ManifPourTous \n#lamanifpourtous \nhttps://t.co/z9AOPYS…" ## [6] "RT @ALC_officiel: #MensongedEtat : #Valls trafique les vidéos de la #ManifPourTous \n#PSmenteur \n#OnLacheRien \n#lamanifpourtous \nhttps://t.c…"
Quelques questions :
- Où tweete t-on le plus?
- Quels sont les tweets les plus retweetés?
- Qui twete le plus?
- Quels sont les mots qui resortent le plus?
- etc..
# Quand est ce qu'il y a eu le plus de tweets en rapport # avec lamanif pour tous? leplusdetweet <- userTimeline("lamanifpourtous", n = 2000, cainfo = "cacert.pem") system.time(leplus.df <- do.call("rbind", lapply(leplusdetweet, as.data.frame)))
user system elapsed 5.39 0.00 5.43
# Attention : Télécharger 2000 tweets on pris environ 7 # secondes sur en 64 bits avec 8 Go de RAM. On peut donc # très rapidement arriver à saturation si l'on y prend # garde. Date de création du tweet Cree.le <- leplus.df$created counts <- table(as.Date(Cree.le)) print(xtable(counts), type = "html")
V1 | |
---|---|
2013-04-04 | 171 |
2013-04-05 | 249 |
2013-04-06 | 10 |
2013-04-07 | 46 |
2013-04-08 | 79 |
2013-04-09 | 90 |
2013-04-10 | 55 |
2013-04-11 | 114 |
2013-04-12 | 113 |
2013-04-13 | 40 |
2013-04-14 | 56 |
2013-04-15 | 68 |
2013-04-16 | 186 |
2013-04-17 | 239 |
2013-04-18 | 122 |
2013-04-19 | 92 |
2013-04-20 | 40 |
2013-04-21 | 173 |
2013-04-22 | 57 |
dates <- as.Date(names(counts)) barplot(counts[counts > 10], col = "sandybrown", las = 2, cex.names = 0.85, main = "Quand a t-on le plus tweeté?")
# Attention à la lectue des dates avec R COmme on pouvait # le prévoir, le point culminant est le jour de la manif du # 5 avril Qui tweete? quitweete <- manif.df$screenName head(quitweete)
[1] “patron_pme” “languillem” “drapsben” “COEURFEULE”
[5] “blantyranha1” “paceo13”
# Qui tweete le plus? counts = table(manif.df$screenName) barplot(counts[counts > 5], col = "skyblue", las = 2, cex.names = 0.9, main = "Qui tweete le plus?")
# combien de caractère par tweet : Utilisation des fonction # de base de R chars_per_tweet = sapply(leplus.df$text, nchar) # Distribution hist(chars_per_tweet, main = "Distribution du nombre de mots par tweets", col = "seagreen2")
# Ou encore : en observant la densité densityplot(chars_per_tweet, col = "orange3")
# Nombre de mots par tweet Cette fonction crée une liste de # mots mots = strsplit(leplus.df$text, " ") head(mots, 2)
[[1]] [1] “\”#manifpourtous" “#24mars”
[3] “:” “images”
[5] “truquées” “ou”
[7] “pas” “?\”,“
[9] "via” “@MetroFrance.”
[11] “http://t.co/aBjFEYayle”
[[2]] [1] “RT” “@MeresVeilleuses:” “Ce”
[4] “soir” “au” “”
[7] “#murdelapaix” “nous” “offrons”
[10] “l'apéro” “au” “600ème”
[13] “follower,” “des” “femmes”
[16] “qui” “vous” “servent”
[19] “un” “apéro” “pour”
[22] “la” “#paix,” “…”
# On crée un vecteur qui contient le nombre de mots par # tweets mot_tweet = sapply(mots, length) # Ditribution barplot(table(mot_tweet), border = NA, main = "Mots par tweet", cex.main = 1, col = "purple")
# Combien de mots clés, mots qui commencent par # et qui # indiquent dans le monde tweet un mot clé de la # conversation. hash = sapply(mots, function(x) length(grep("#", x))) unclass(table(hash))
hash 0 1 2 3 4 5 6 7 8 245 509 588 380 201 59 13 4 1
# Distribution des tweets retweetés hist(leplus.df$retweetCount, col = "skyblue2", xlab = "", main = "Tweets retweetés")
Relation entre le nombre de caractères par tweet et le nombre de mots par tweet par régression linéaire simple.
plot(df$chars, df$words, xlab = "Nb de caractères par tweets", ylab = "nombre de mots par tweets", main = "", col = "gray20", pch = 20) # Intervalle de confiance polygon(c(carac, rev(carac))[is.na(vu) == FALSE], vu[is.na(vu) == FALSE], col = "lavender", border = FALSE) lines(carac, prev$fit, col = "tomato3", lwd = 3) lines(carac, prev$fit + 7 * prev$se.fit, col = "thistle4", lty = 2) lines(carac, prev$fit - 7 * prev$se.fit, col = "thistle4", lty = 2) lines(carac, prev$fit + 10 * prev$se.fit, col = "darkgoldenrod3", lwd = 2) lines(carac, prev$fit - 10 * prev$se.fit, col = "darkgoldenrod3", lwd = 2)
Textmining
Une petite classification
Une analyse geographique des tweets selon un thème
Une illustration d'un graphique interactif animé à partir des données de stats et de twitter
Il existe via xml, une autre façon d'avoir accès aux données de tweet : Attention si vous êtes en entreprise d'ouvrir les ports qui vont bien. Repris de (donner la source)
mydata.vectors <- character(0) for (page in c(1:15)) { twitter_q <- URLencode('#cahuzac'); twitter_url = paste('http://search.twitter.com/search.atom?q=', twitter_q,'&rpp=100&page=', page, sep=''); mydata.xml <- xmlParseDoc(twitter_url, asText=F); mydata.vector <- xpathSApply(mydata.xml, '//s:entry/s:title', xmlValue,namespaces =c('s'='http://www.w3.org/2005/Atom')); mydata.vectors <- c(mydata.vector, mydata.vectors); }
On ne peut charger plus de 1500 tweets de façon générale. L'opération est plutôt rapide.
Quelques fonctions du package tm
# L'outil de base est le corpus mydata.corpus <- Corpus(VectorSource(mydata.vectors)) # On met tous en miuscules mydata.corpus <- tm_map(mydata.corpus, tolower) # On enlève la ponctuation mydata.corpus <- tm_map(mydata.corpus, removePunctuation) # On construit un term-document matrix mydata.dtm <- TermDocumentMatrix(mydata.corpus) # Que contient un document-term matrix? mydata.dtm ## A term-document matrix (3952 terms, 1490 documents) ## ## Non-/sparse entries: 18302/5870178 ## Sparsity : 100% ## Maximal term length: 33 ## Weighting : term frequency (tf) # Quels sont les termes les plus fréquents dans # le document matrix? b = findFreqTerms(mydata.dtm, lowfreq = 20) tail(b, 10) ## [1] "taubira" "tous" "tout" "toute" "une" "valeurs" "valls" ## [8] "via" "vous" "yeux" # On peut chercher les associations entre mots # calculé par un score d'association # (corrélation) a = findAssocs(mydata.dtm, "cahuzac", corlimit = 0.1) head(a) ## christineboutin mémoire donnait httptc… ## 0.54 0.54 0.53 0.53 ## avant parlait ## 0.50 0.50 # On enlève les termes rares selon un coéficient # de rareté mydata.dtm2 <- removeSparseTerms(mydata.dtm, sparse = 0.95) # On convertit en data.frame ## [1] 24 ## [1] 1490 # Une CAH sur les corpus les plus retouvés d <- dist(mydata.df.scale, method = "euclidean") fit <- hclust(d, method = "ward") plot(fit) groups <- cutree(fit, k = 5) rect.hclust(fit, k = 5, border = "mediumaquamarine")
cor.mesvars <- cor(t(mydata.df)) row.names(cor.mesvars) = colnames(cor.mesvars) cor.plot <- levelplot(cor.mesvars, scales = list(x = list(rot = 90)), xlab = "", ylab = "", main = "Corrélation entre mots clés", cex = 1) print(cor.plot)
Avec un peu de cartographie
- Où tweete t-on le plus dans le monde?
filterStream("tweet_monde.json", locations = c(-180, -90, 180, 90), timeout = 20, oauth = myacc) ## Capturing tweets... ## Connection to Twitter stream was closed after 20 seconds with 2586 kB ## received. tweets.df <- parseTweets("tweet_monde.json", verbose = FALSE) head(tweets.df$text, 5) ## [1] "Hari ni hujan la horay blah tido puas2" ## [2] "Just received info that the suspect #2 might be wearing a bomb. Suspect #1 was wearing a bomb when he was killed. #Watertown #Boston" ## [3] "Q tl estuvo @mikel_ar94 ayer a la noche con la mantica y el periódico?? Jajajaja" ## [4] "@NguyenLiisa hahaha yeah shes dumb. Lol wasnt our fault that we got so close ! Especially because our name is Lisa <ed><U+00A0><U+00BD><ed><U+00B8><U+008A><ed><U+00A0><U+00BD><ed><U+00B8><U+0098>" ## [5] "@tutisiialamiyah bukannya tadi die lagi maen sama si itu2" # Quels sont les pays d'où vienne tle plus de tweet en # moyenne a = table(tweets.df$country) barplot(a[a > mean(a)], col = "orchid4", las = 2, cex.names = 1, main = "Pays qui ont le plus tweeté?")
# Quelle sont les 5 langues les plus utilisées ? a = table(tweets.df$lang) ab = sort(a, decreasing = T)[1:5] slices <- ab lbls <- c("Anglais", "Espagnol", "Indonésien", "Turque", "Portugais") pct <- round(slices/sum(slices) * 100) lbls <- paste(lbls, pct) # add percents to labels lbls <- paste(lbls, "%", sep = "") # ad % to labels couleur = brewer.pal(n = 5, name = "Set1") pie(slices, labels = lbls, col = couleur, main = "les 5 langues les plus utilisées", cex = 0.7)
On pourrait faire la même chose avec les pays
Sur unr carte du monde, cela donne :
points <- data.frame(x = as.numeric(tweets.df$lon), y = as.numeric(tweets.df$lat)) map.data <- map_data("world") p <- ggplot(map.data) + geom_map(aes(map_id = region), map = map.data, fill = "whitesmoke", color = "grey30", size = 0.2) + expand_limits(x = map.data$long, y = map.data$lat) + theme(axis.line = element_blank(), axis.text = element_blank(), axis.ticks = element_blank(), axis.title = element_blank(), panel.background = element_blank(), panel.border = element_blank(), panel.grid.major = element_blank(), plot.background = element_blank()) p = p + geom_point(data = points, aes(x = x, y = y), size = 1, alpha = 1/5, color = "indianred2") p
On peut aussi s'intéresser à partir des données de tweeter aux opinions positives (côte de popularité de Francois Hollande et celle de son rival Sarkoy par exemple entre deux dates. Les côtes de popularité sont disponible sur le site d'opinionway
On a constitué des données qui récupéraient des tweets où étaient mentionnés leurs deux noms entre avril 2012 et avril 2013; On définit un corpus de mots positifs et on fait un lien avec le taux de chômage des mois concernés;
l'analyse interactive que nous donne le package googlevis est présentée ci dessous :
# require(GoogleVis) M <- gvisMotionChart(dt, "key", "date", date.format = "%YW%W") print(M, "chart")_Le code pour créer tous les objets de ce post est disponible sur demande_
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.