L’objectif ici est d’exploiter les émoticônes et émojis présents dans un corpus (de tweets).

Les données

On utilise les tweets du corpus #confinement, ici le fichier df_sample

df_sample<- readRDS(file = "df_sample.rds")

Les émojis

On utilisera les library ‘ggtext’ et ‘emo’ pour récupérer le dictionnaire des émojis et des caractères encodés et pour les afficher dans GGPlot. On s’inspirera très largement de ce site[https://www.hvitfeldt.me/blog/real-emojis-in-ggplot2/] pour le code.

La difficulté vient du fait que GGPlot ne sait pas afficher des images. On va donc chercher en ligne les images représentants les émojis pour les intégrer au graphique. On construit pour cela deux fonctions, et grâce au package ‘ggtext’ on pourra afficher les images correspondantes :

emoji_to_link <- function(x) {
  paste0("https://emojipedia.org/emoji/",x) %>%
    read_html() %>%
    html_nodes("tr td a") %>%
    .[1] %>%
    html_attr("href") %>%
    paste0("https://emojipedia.org/", .) %>%
    read_html() %>%
    html_node('div[class="vendor-image"] img') %>%
    html_attr("src")
}

link_to_img <- function(x, size = 25) {
  paste0("<img src='", x, "' width='", size, "'/>")
}

Grâce au package ‘emo’, on extrait facilement des tweets les emojis présentes et on peut les représenter graphiquement :

happy_emojis <- df_sample %>%
  mutate(emoji = emo::ji_extract_all(text)) %>%  #on extrait les emojis sous forme de liste
  unnest(cols = c(emoji)) %>% #on crée une ligne par émoji
  count(emoji, sort = TRUE) #on compte les occurrences

top_happy <- happy_emojis %>%
  slice(1:10) %>% #on ne garde que les 10 émojis les plus fréquents
  mutate(url = map_chr(emoji, slowly(~emoji_to_link(.x), rate_delay(1))),
         label = link_to_img(url)) #on récupère les images correspondantes en ligne


offset <- max(top_happy$n) / 20 #pour la position des émojis sur le graphique


#Le graphique :
top_happy %>%
  ggplot(aes(fct_reorder(emoji, n, .desc = FALSE), n, label = label, fill=label)) +
  geom_col() +
  geom_richtext(aes(y = n + offset), fill = NA, label.color = NA,
                label.padding = grid::unit(rep(0, 4), "pt")
  ) +
  theme(axis.ticks.x = element_blank(),
        axis.text.x = element_blank()) +
  labs(x = NULL) +
  theme_minimal()+
  coord_flip()+
  theme(axis.text.x = element_markdown(),legend.position = "NONE") +
  labs(x = NULL, y = "Count", 
       title = "Emojis used in (small sample) of 'confinement' tweets",
       caption = "\nSource: Data collected by Benavent C. from Twitter's REST API via rtweet")

Evolution temporelle

Bon, là c’est un essai, je n’arrive pas à utiliser ts_plot + ggplot…

Analyse du sentiment

On pourrait utiliser du machine learning couplé à l’analyse du sentiment des textes, là on utilise un dictionnaire des sentiments des emojis fait par P. Kralj Novak, J. Smailovic, B. Sluban, I. Mozetic [http://kt.ijs.si/data/Emoji_sentiment_ranking/index.html]. Ils ont constitué un set d’émojis et associés avec un score de sentiment. malheureusement, tous les emojis de notre corpus ne sont pas annotés dans ce dictionnaire…

On va récupérer le dictionnaire directement en ligne, on l’associe avec notre fichier des emojis (merci à today-is-a-good-day[https://github.com/today-is-a-good-day/emojis/blob/master/emoji_analysis.R]), et c’est parti.

url <- "http://kt.ijs.si/data/Emoji_sentiment_ranking/index.html"

# get emoticons
emojis_raw <- url %>%
  read_html() %>%
  html_table() %>%
  data.frame() %>%
  select(-Image.twemoji., -Sentiment.bar.c.i..95..)
names(emojis_raw) <- c("char", "unicode", "occurrences", "position", "negative", 
                       "neutral", "positive", "sentiment_score", "description", 
                       "block")


emo_sent <- df_sample %>%
  mutate(day=day(created_at))%>%
  mutate(emoji = emo::ji_extract_all(text))%>%
  unnest(cols = c(emoji))%>%
  inner_join(emojis_raw, by=c("emoji"="char"))

# Les tweets les plus négatifs
emo_sent%>%
  group_by(text)%>%
  summarise(sentiment=sum(sentiment_score))%>%
  ungroup()%>%
  arrange(sentiment)%>%
  head(10)
## # A tibble: 10 x 2
##    text                                                                sentiment
##    <chr>                                                                   <dbl>
##  1 "#confinementjour5 je viens de perdre ma 249eme partie de morpion ~    -147. 
##  2 "Ptdrrrrrrr le confinement vous rend fou tu te fais contrôler par ~    -102. 
##  3 "Ecoutez cette bande de bras cassés... \U0001f624\U0001f926<U+200D><U+2642><U+FE0F>\U00~       -33.6
##  4 "\U0001f4ccPropagation fulgurante du #Covid_19 aux États-Unis  #Co~     -17.6
##  5 "\U0001f637 Une affiche réalisée il y a deux ans, qui prend triste~     -17.1
##  6 "\U0001f1eb\U0001f1f7 Constat. Clair et précis, point ! Avec cette~     -15.4
##  7 "Dur de retenir ses larmes après avoir lu ce message \U0001f62d\U0~     -15.3
##  8 "Bonjour, \n\nUn schéma pour comprendre pourquoi le confinement es~     -14.2
##  9 "Nos équipes ont mis la main sur la vidéo du dernier Conseil des m~     -14.2
## 10 "Yassine victime de la barbarie policière\U0001f621\U0001f621  Têt~     -13.1
# Les tweets les plus positifs
emo_sent%>%
  group_by(text)%>%
  summarise(sentiment=sum(sentiment_score))%>%
  ungroup()%>%
  arrange(sentiment)%>%
  tail(10)
## # A tibble: 10 x 2
##    text                                                                sentiment
##    <chr>                                                                   <dbl>
##  1 "\U0001f534 EXCLUSIF \U0001f534\nNos équipes ont mis la main sur l~      197.
##  2 "\U0001f55b Cette nuit, nous gagnons une heure de confinement :\n ~      208.
##  3 "Qui aurait pu prévoir ça ? Qui ?\n\n#CONFINEMENTJOUR11 #confineme~      209.
##  4 "#ChezJamy - Jour 3 \n\n\U0001f3e1 Aujourd’hui dans mon jardin, je~      210.
##  5 "Nos jeunes du 93 c'est quand même autre chose que ceux des quarti~      212.
##  6 "\U0001f4aa #ConfinementJour10 : on tient bon !\nPas de quoi être ~      305.
##  7 "<U+267B> C'est le #Confinementjour2... mais aussi la #JournéeMondialeDuR~      314.
##  8 "La promenade du chien en #ConfinementJour3 <U+270C><U+FE0F>\U0001f436\U0001f60a~      343.
##  9 "Y’a un gars qui a créé question pour un Balcon\U0001f602 et tout ~      388.
## 10 "#ConfinementJour4 : savez-vous pourquoi les jours sont de plus en~      439.
#Graphique de l'évolution du sentiment moyen dans le temps

emo_sent%>%
  group_by(day)%>%
  summarise(sentiment=mean(sentiment_score))%>%
  arrange(sentiment)%>%
  ggplot(aes(day,sentiment))+
  geom_line(color="darkblue")+
  geom_point()+
  theme_light()+
  labs(x = "Day", y = "Mean sentiment expressed by emojis in 'confinement' tweets", 
       title = "Evolution of sentiment expressed in (small sample) of 'confinement' tweets",
       caption = "\nSource: Data collected by Benavent C. from Twitter's REST API via rtweet")

Nuage d’emojis

Bon, ça j’ai pas encore trouvé…

library(wordcloud)

wordcloud(happy_emojis$emoji, happy_emojis$n)