TOP C’EST PARTI!

Installation des Packages

#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!

Maître Gims, le voici!

RECUPERATION DES PAROLES DE CHANSONS AVEC LE WEB SCRAPPING

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!

le tableau est sublimal!

APPUREMENT DES DATA ET DIGESTION

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!

Tout est bien qui commence bien!

Les donnees sont prêtes, passons a l’analyse propement dite.

GIMS : QU’ES CE QUE DIT SON STYLO ?

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.

AUTRE VISUALISATION:CONSTRUCTION DU WORDCLOUD

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)

REGARDONS A LA LOUPE CHACUN DES ALBUMS POUR RIEN LOUPER

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)] 

TOP TITRES D’EMOTION BAD et GOOD : Sorties Vraisemblables

BADs thinks

  • First Bad titre : Epuisé de l’album Subliminal avec une note de (-20)
  • Second Bad titre : Je me tire de l’album Subliminal avec une note de (-15)
  • Dernier Bad titre :La vérité de l’album Ceinture Noir avec une note de (-9)
#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!')

Resumer du titre EPUISE

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')  

GOODs Thinks

  • First Good titre : Oulala de l’album Ceinture Noir avec une note de (22)
  • Second Good titre : Freedom de l’album Subliminal avec une note de (16)
  • Dernier Good titre :Merci Maman de l’album Ceinture Noir avec une note de (9)
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!')

Resumer des 3 Good Titres