#Créer une fonction qui installe des packages
Install_And_Load <- function(packages) {
k <- packages[!(packages %in% installed.packages()[,"Package"])];
if(length(k))
{install.packages(k, repos='https://cran.rstudio.com/',dep=T);}
for(package_name in packages)
{library(package_name,character.only=TRUE, quietly = TRUE);}
}
packgims=c("readbitmap","jpeg","grDevices","graphics","XML",
"httr","rvest","stringr","xtable","knitr",
"kableExtra","tidytext","NLP","tm","dplyr",
"ggplot2","reshape2","wordcloud","wordcloud2",
"tidyr","reshape","slam")
Install_And_Load(packgims)Vous allez decouvrir ici comment j’ai crée un scrapper en R pour recupérer des paroles de chansons de Gims et la façon dont je les ai etudiées grâce au text mining, une methode qui permet de transformer des textes en données. Ce fut trop cool!!!
La finalite est de mesurer les sentiments dominants dans chacun de ses albums et les mots les plus utilisés dans ses textes.
Nous sommes en 2019, le gars au lunettes, le boss de Vortex, le producteur du Beerus Sama, le deuxieme plus grand vendeur de disque en France de tout les temps … . Gims plus a présenter, vous connaitrez la marque de son stylo et les sentiments de ces écrits vous affranchiront !
#insérer une image dans le document
knitr::include_graphics(paste0(chemin_base,"mg/MLjpg.jpg"))Maître Gims, le voici!
Après avoir récuperer les URL de chaque page d’album, ensuite les URL des titres de chaque album et enfin extraire les paroles de chaque titre d’album simplement.
Voici ce qu’on obtient, c’est génial n’es ce pas?
artist <- "/paroles-maitre-gims"
url_website <-"https://paroles2chansons.lemonde.fr" #Site de paroles de chansons
url_repo <- "/artists/"
url_artist <- paste0(url_website,artist) #lien à rechercher
request <- GET(url_artist) #Accès au lien
doc <- htmlParse(request, asText = TRUE)
hrefs <- xpathSApply(doc, "//div/a", xmlGetAttr, 'href')
url_songs <- grep("album", hrefs, value = TRUE) #extraire tous les liens qui accèdent aux albums
#Créer la table des albums
url_album=data.frame(url_album=url_songs, album=gsub(".html"," ",str_sub(url_songs,63,1000)))
url_album$url_album=as.character(url_album$url_album)
#Extraire les titres des albums
docq <- htmlParse(GET(url_album$url_album[1]), asText = TRUE)
hrefsq <- xpathSApply(docq, "//div/a", xmlGetAttr, 'href')
url_lirics <- data.frame(url_paroles=grep("paroles-maitre-gims/paroles",hrefsq, value = TRUE),album=url_album$album[1])
for (i in 2: nrow(url_album)){
docq <- htmlParse(GET(url_album$url_album[i]), asText = TRUE)
hrefsq <- xpathSApply(docq, "//div/a", xmlGetAttr, 'href')
url_liric <- data.frame(url_paroles=grep("paroles-maitre-gims/paroles",hrefsq, value = TRUE),album=url_album$album[i])
url_lirics=rbind(url_lirics,url_liric)
}
url_lirics$url_paroles=as.character(url_lirics$url_paroles)
url_lirics$titre=gsub(".html"," ",str_sub(url_lirics$url_paroles,65,1000))
#Extraire les paroles des titres
docq <- read_html(GET(url_lirics$url_paroles[1]))
hrefsq=html_nodes(docq,"p")
hrefsq=html_text(hrefsq, trim = TRUE)
hrefs=hrefsq[2]
hrefs= gsub('([[:upper:]])','\\1',hrefs)
hrefs= gsub('\r\n',' ',hrefs)
url_text <- data.frame(url_paroles=url_lirics$url_paroles[1],album=url_lirics$album[1],titre=url_lirics$titre[1],paroles=hrefs)
for (i in 2: nrow(url_lirics)){
docs <- read_html(GET(url_lirics$url_paroles[i]))
hrefsq=html_nodes(docs,"p")
hrefsq=html_text(hrefsq, trim = TRUE)
hrefs=hrefsq[2]
hrefs= gsub('([[:upper:]])','\\1',hrefs)
hrefs= gsub('\r\n',' ',hrefs)
url_texts <- data.frame(url_paroles=url_lirics$url_paroles[i],album=url_lirics$album[i],titre=url_lirics$titre[i],paroles=hrefs)
url_text=rbind(url_texts,url_text)
}
#Arranger les donner
url_text$paroles=as.character(url_text$paroles)
url_text$album=as.character(url_text$album)
url_text$titre=str_trim(url_text$titre)
url_text$album=str_trim(url_text$album)
#Extraire les 3 albums phares de l'artiste
Ablbum=c("ceinture-noire","mon-crur-avait-raison","subliminal-la-face-cachee")
url_textd=url_text[(url_text$album=="ceinture-noire")|(url_text$album=="mon-crur-avait-raison")|(url_text$album=="subliminal-la-face-cachee"),]
knitr::include_graphics(paste0(chemin_base,"mg/Capture1.PNG"))le tableau est sublimal!
Afin de mieux analyser les sentiments qui se degagent dans les paroles de MG, il faut disposer differement les données; Plutot que d’avoir tout le texte d’une chanson sur une seule ligne, il faut passer a une table avec un mot par ligne. On n’oublie pas d’éliminier les mots inutiles telque le fameux “yeeah” de Gims.
url_text_MG = url_textd
#Fonction qui élimine les accents
Unaccent <- function(text) {
text <- gsub("['`^~\"]", " ", text)
text <- iconv(text,from="UTF-8", to="ASCII//TRANSLIT//IGNORE")
text <- gsub("['`^~\"]", "", text)
return(text)
}
url_text_MG$paroles=Unaccent(url_text_MG$paroles) #Supprimer les accents dans les textes
url_text_MG$paroles=tolower(url_text_MG$paroles) #Mettre tous les mots en minuscule
url_text_MG$paroles=removeWords(url_text_MG$paroles, stopwords("french"))#Supprimer les mots inutiles en français tels que "la","le" ...
url_text_MG$paroles=removePunctuation(url_text_MG$paroles)#Supprimer la ponctuation
url_text_MG$paroles=removeNumbers(url_text_MG$paroles)#Supprimer les chiffres
custom_stopwords <- c("oh","a","ooh","oh","oooh","umh","hum","huh","aaah","aah","ah","bah","yeah","tah","ha","eh","haaaaaaaaaaaaaaaaaaaaaaaaaaa","ça","aaaah") #Identifier les mots inutiles dans les textes étudiés
url_text_MG$paroles=removeWords(url_text_MG$paroles, custom_stopwords)
url_text_MG <- url_text_MG %>%unnest_tokens(word, paroles) #Decouper les textes en mots
url_text_MG$linenumber <- NA
nrowurl_text_MG <- nrow(url_text_MG)
url_text_MG$linenumber <- 1:nrow(url_text_MG)
#Affichage des données qu'on obtient
knitr::include_graphics(paste0(chemin_base,"mg/tempsnip.png"))Tout est bien qui commence bien!
Les donnees sont prêtes, passons a l’analyse propement dite.
Pour cette analyse j’utilise le lexique bing qui catégorise les mots de facon binaire : positif vs negatif. Le lexique comporte 6 788 mots categorisés.
L’idée est de comparer notre dataset de paroles au lexique bing et celui de Darwin (à créer), le premier à avoir travailler sur les émotions.
Grâce à la fonction inner_join(). Les mots sont ensuite rangés par fréquence.
#Recupérer la table de mots que j'ai crée à partir des travaux de Darwin
darwin=read.csv2(paste0(chemin_base,"words.csv"), stringsAsFactors = FALSE )
darwin$words=tolower(toupper(darwin$words))
#Recupérer le exique de bing disponible sous R
bing <- get_sentiments("bing")
#Fusionner le lexique de bing et celui de Darwin
names(darwin)=names(bing)
bings=rbind(bing,darwin)
#Procéder à la correspondance entre les mots de gims et ceux de bing afin de trouver leur catégorie (positive ou negative)
bing_word_counts <- url_text_MG %>%inner_join(bings) %>%count(word, sentiment, sort = TRUE) %>%ungroup()
#Tracer le diagramme des mots en fonction de leur sentiment
bing_word_counts %>%
filter(n > 5) %>%
mutate(n = ifelse(sentiment == "negative", -n, n)) %>%
mutate(word = reorder(word, n)) %>%
ggplot(aes(word, n, fill = sentiment)) +
geom_bar(stat = "identity") +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
ylab("Poids des sentiments")Il a TOUT DIRE sur sa VIE dans ses trois albums avec un sentiment penchant plus sur des sentiments assez tristes.
url_text_MG %>%
inner_join(bings) %>%
count(word, sentiment, sort = TRUE) %>%
acast(word ~ sentiment, value.var = "n", fill = 0) %>%
comparison.cloud(colors = c("#FF0000", "#33FF33"),
max.words = 100)On va s’interesser à l’evolution des sentiments au sein des albums. Pour une meilleure lisibilite, pour chaque titre d’un album on cree des sous-ensemble d’un regroupement de 50 mots. Chacun de ses sous-ensemble est ensuite comparé au lexique bing-Darwin et obtient une note de sentiment. Plus le sous-ensemble comporte de mots positifs et plus la note sera elevée, plus il comporte de mots négatifs et plus la note est basse.
Ce que nous obtenous est toout simplement DATASIENCETIQUE.
#Table des notes des titres d'album
janeaustensentiment_titre <- url_text_MG %>%
inner_join(bings) %>%
count(titre, index = linenumber %/% 50,sentiment) %>%
spread(sentiment, n, fill = 0) %>%
mutate(sentiment = positive - negative)
#Fonction qui additionne plusieurs variables en fonction d'un critère
SumDouble <-function(X,na.rm)
{
sum(as.double(X),na.rm = TRUE)
}
Sentiment_Titre=aggregate(janeaustensentiment_titre[,c("negative","positive","sentiment")],by=list(janeaustensentiment_titre$titre),SumDouble,na.rm=TRUE)
names(Sentiment_Titre)[1]="Titre"
Sentiment_Titre$Album=url_text_MG$album[match(Sentiment_Titre$Titre,url_text_MG$titre)] #Isoler les titres dont le sentiment negatif est dominant et visualiser
sentiment_bad=Sentiment_Titre[Sentiment_Titre$sentiment<0,]
sentiment_bad$sentiment=-sentiment_bad$sentiment
sentiment_bad %>%
arrange(desc(sentiment)) %>%
head(n=10) %>%
arrange(sentiment) %>%
mutate(Titre=factor(Titre,Titre)) %>%
ggplot( aes(x=Titre, y=sentiment)) +
geom_segment( aes(x=Titre, xend=Titre, y=0, yend=sentiment), color="grey", size=1) +
geom_point( color="red", size=4, alpha=0.6) +
theme_light() +
coord_flip() +
theme(
panel.grid.major.y = element_blank(),
panel.border = element_blank(),
axis.ticks.y = element_blank()
) +
xlab("") +
ylab("") +
ggtitle('Top 10 des Titres ayant plus de sentiments tristes!')a=url_text_MG[url_text_MG$titre=="epuise","word"]
docs=Corpus(VectorSource(a), readerControl =list( language = "fr"))
#inspect(docs)
dtm <- TermDocumentMatrix(docs)
m <- as.matrix(dtm)
v <- sort(rowSums(m),decreasing=TRUE)
d <- data.frame(word = names(v),freq=v)
set.seed(1234)
par(bg="black")
wordcloud(words = d$word, freq = d$freq, min.freq = 2,
max.words=200, random.order=FALSE, rot.per=0.1,
colors=brewer.pal(14, "Dark2"),shape = 'disque') sentiment_good=Sentiment_Titre[Sentiment_Titre$sentiment>0,]
sentiment_good %>%
arrange(desc(sentiment)) %>%
head(n=10) %>%
arrange(sentiment) %>%
mutate(Titre=factor(Titre,Titre)) %>%
ggplot( aes(x=Titre, y=sentiment)) +
geom_segment( aes(x=Titre, xend=Titre, y=0, yend=sentiment), color="grey", size=1) +
geom_point( color="green", size=4, alpha=0.6) +
theme_light() +
coord_flip() +
theme(
panel.grid.major.y = element_blank(),
panel.border = element_blank(),
axis.ticks.y = element_blank()
) +
xlab("") +
ylab("") +
ggtitle('Top 10 des Titres ayant plus de sentiments aimables!')