Italie
Ce script est une exploration de l’intérêt des données sociales pour l’étude des phénomènes humains. Celui qui nous intéresse, l’épidémie de covid19, est à l’évidence majeur. C’est un choc inattendu, un cygne noir.
Ses conséquences sont sanitaires, sociales, politiques et économiques. La manière dont les gens le vivent, du moins en France résulte d’un régime d’exception, largement adopté à travers les pays, qui vise à maintenir au domicile toutes les personnes non nécessaires au traitement de la question sanitaire, de celle de l’approvisionnement alimentaire et pharmaceutiques, et des productions fondamentales.
L’expérience vécue est celle du confinement. Une recommandation devenue obligation à rester chez soi, un dispositif réglementaire qui contrôle, nudge et sanctionne, une privation, espérons temporaire, de liberté de déplacement. Une vie sociale confinée au foyer et aux moyens de communiquer. Les mots du confinement sont bien rendu par autourdumot, et il est utile d’en revenir à sa définition
Un des réseaux où les états d’âmes peuvent s’exprimer librement est naturellement Twitter. Très rapidement a émergé un hashtag #confinementjour1 puis 2 et 3, et voué à de longs jours. Il cristalise les intentions de dire son expérience et de partager ses états d’âmes. L’humour y a une place importante. C’est ce canal que nous allons utiliser pour tester la sensibilité des instruments de mesure du sentiment, et, espérons, mieux comprendre la réaction des populations à un choc anthropologique brutal (le choc c’est la rencontre d’une société avancée et mobile, et d’une contingence naturelle : un virus qui circule de bouche en bouche et se deplace en business class).
Pour les données factuelles, le dashboard de la John Hopskins University restera un cas d’école en matière d’open dat , l’initiative du geg au travers de son site le grand continent est similaire et remarquable. Ils sont notre inspiration pour un processus qui vise à intégrer la collecte, le traitement et la repropagation des données.
Nous nous intéresserons mois au virus et à la maladie, moins au choc économique et social que le confinement va produire, qu’à la manière dont les gens vivent ce choc jour après jour, en capturant l’écume sociale et en tentant d’y mesurer les sentiments, les émotions et les préoccupations.
On va lancer nos filets de pêche dans ce petit courant, en espérant que ce sera un caillou de plus pour retrouver le chemin d’une humanité en bonne santé.
L’approche dans ce script est principalement baromètrique. On cherche simplement à représenter l’évolution des indicateurs dans le temps d’abord à une échelle horaire, puis journalière.
Le but de l’exercice est de mesurer le sentiment dans la période de confinement décidée par l’Etat pour lutter contre l’épidémie de covid19, au travers des tweets générés avec le hashtag #confinementjourxx qui signale clairement l’intention de partager son sentiment, son humeur, sa pensée, son expérience, ses états d’âme.
C’est un fil tenu qui nous semble-t-il significatif, moins au sens de la représentation de l’humeur générale que d’une cohérence éditoriale. Il s’inscrit dans un projet expressif assez bien identifiable et se révèlent une convention capable de durer quotidiennent dans les trending-topic de twitter.
A cette fin on utilise les packages suivants.
On utilise l’API de twitter via le package rtweet
pour aller chercher les tweets contenant le hashtag “confinementjour$”
Les limites de l’API free de twitter sont de 15000 requêtes par 15mn, on emploie donc le paramètre retryonratelimit = TRUE
pour poursuivre la requête en supportant la latence. Celà représente facilement quelques heures de requêtage. On sauvegarde donc rapidement le résultat dans un fichier fixe, qu’on pourra rappeler plus tard pour analyse, avec la fonction write_rds
.
On a commencé à capturer les données le 9ème jour, puis chaque jour sur le jour de la veille. Au 15 jours on est 1, 1 millions de tweet, avec un flux journalier de l’ordre de 50 k.
IMPORTANT : on exclue les retweets, mais il peut être utile de regarder aussi avec le corpus total : il est possible que par un effet de renforcement la tendance de la production primaire ne soit pas celle de la production secondaire. Les suiveurs peuvent selectionner dans le registre de la production certains éléments qui leurs plaisent. Et imposer une sorte de torsion. C’est un sujet d’étude à développer.
On retrace ici la production quotidiennes des tweets, rt quotes et reply. On notera qu’en journée l’échantillon représente plusieurs milliers d’observations à l’heure ce qui assure une grande sensibilité des mesures. On utilise ts_plot.
On observe un effet d’usure, un rebond le dimanche, et un cycle quotidien. Aux premiers jours il semble qu’on postait plus le matin que le soir, après quelques jours la tendance s’est renversée.
## plot time series of tweets
ts_plot(df_nrc, "1 hours", color="darkblue") +
ggplot2::theme_minimal() +
ggplot2::theme(plot.title = ggplot2::element_text(face = "bold")) +
ggplot2::labs(
x = NULL, y = NULL,
title = "Fréquence des posts twitters sur #confinementjour",
subtitle = "Nombre de tweets par heure",
caption = "\nSource: Data collected by Benavent C. from Twitter's REST API via rtweet"
)+ scale_x_datetime(date_breaks = "1 day", labels = scales::label_date_short())
L’analyse du sentiment peut se faire avec plusieurs outils, nous employons ceux-ci :
voir le script calcul pour le détail de la mise en oeuvre de ces procédures.
Un des objectifs est de faire une analyse de fiabilité des indicateurs de sentiments.On complète avec les émotion et les sujets de préoccupation.
L’unité de temps est l’heure dans un premier temps, et la journée. Des échelles intermédiaires pourront être développées.
Un contrôle pour les calcul intermédiaires en échantillonnant.
On commence par l’analyse du sentiment simple, puis à celui des émotions.
Avec l’outil NCR deux indicateurs sont fournis: la densité de termes positifs et de termes négatifs, exprimé en nombre de mots d’un texte qui ont une valence ou positive, ou negative. Ce sont donc comme deux séries distinctes.
Examinons d’abord la distribution des émotions négatives et positives. On examine dans la foulée leur distribution conjointe.
https://a-little-book-of-r-for-time-series.readthedocs.io/en/latest/src/timeseries.html
par convention le zero est partagé entre les positive et les negatifs
#statistiques : moyenne et ecartype
s_mean1<-round(mean(df_nrc$negative),2)
s_mean2<-round(mean(df_nrc$positive),2)
s_std1<-round(sd(df_nrc$negative),2)
s_std2<-round(sd(df_nrc$positive),2)
#histogram
g1<-ggplot(df_nrc, aes(x=negative))+
geom_histogram(binwidth=1,fill="red")+
theme_minimal()+ scale_x_reverse()+
ggplot2::annotate("text", x=7, y=200000, label= paste0("moyenne=",s_mean1," \n ecart type",s_std1))
g2<-ggplot(df_nrc, aes(x=positive))+
geom_histogram(binwidth=1,fill="darkgreen")+
theme_minimal()+xlim(-1,15)+
ggplot2::annotate("text", x=7, y=200000, label= paste0("moyenne=",s_mean2," \n ecart type",s_std2))
grid.arrange(g1,g2,ncol=2)
ggplot(df_nrc,aes(x=positive, y=negative))+geom_point(position="jitter")+theme_minimal()+geom_smooth(method="gam")
On represente ici l’évolution des scores de positivité et de négativité, ainsi que leur différence qui donne le sentiment moyen si on pense que les points négatifs éffacent les points positifs. On garde en tête l’idée de ce carré magique que le négatif n’est pas que l’antonyme du positif.
sentevol<-df_nrc %>% group_by(month,day,hour) %>% mutate(n=1) %>%summarise(positive=mean(positive, na.rm=TRUE),negative=mean(negative, na.rm=TRUE), n=sum(n))
sentevol$date<-paste0("2020","-",sentevol$month,"-",sentevol$day," ",sentevol$hour,":00:00")
sentevol$date2 <- as.POSIXct(strptime(sentevol$date, "%Y-%m-%d %H:%M:%S"))
foo<-sentevol %>% ungroup %>%select(date2, negative,positive) %>% mutate(negative=-1*negative, sentiment=positive+negative)
library(reshape2)
foo<-melt(foo, id=c("date2"))
ggplot(foo, aes(x=date2,y=value,group=variable))+
geom_line(size=1,aes(color=variable))+
theme(axis.text.x=element_text(angle = 60, vjust = 0.5))+
theme_minimal()+ stat_smooth( aes(color =variable, fill = variable), method = "loess")+
labs(x = NULL, y = NULL,
title = "Evolution de la valence du sentiment du confinement", y="Valence (+/-)",x="dates (par heures)",
subtitle = "Valence par heure",
caption = "\nSource: Data collected by Benavent C. from Twitter's REST API via rtweet"
)+ scale_x_datetime(date_breaks = "1 day", labels = scales::label_date_short())
df_nrc$day<-as.numeric(format(df_nrc$created_at, "%d")) # jour
df_nrc$month<-as.numeric(format(df_nrc$created_at, "%m")) # mois
df_nrc$hour<-as.numeric(format(df_nrc$created_at, "%H")) # heure
df_nrc$year<-2020 # heure
df_nrc<- df_nrc %>% mutate(Jour=ifelse(month == 3,day-16 ,ifelse(month==4,day+15,0) ))
ggplot(df_nrc,aes(x=Jour))+
geom_bar(fill="gold4")+
theme_minimal()+
labs(title="# de tweets par jour")+
facet_wrap(vars(is_retweet),ncol=1,scales="free")
sentevol<-df_nrc %>% group_by(Jour) %>% mutate(n=1) %>%summarise(positive=mean(positive, na.rm=TRUE),negative=mean(negative, na.rm=TRUE), n=sum(n))
foo<-sentevol %>% ungroup %>%select(Jour, negative,positive) %>% mutate(negative=-1*negative, sentiment=positive+negative)
library(reshape2)
foo<-melt(foo, id=c("Jour")) %>%filter(Jour<33)
ggplot(foo, aes(x=Jour,y=value,group=variable))+
geom_line(size=1,aes(color=variable))+
theme(axis.text.x=element_text(angle = 60, vjust = 0.5))+
theme_minimal()+ stat_smooth( aes(color =variable, fill = variable), method = "loess")+
labs(x = NULL, y = NULL,
title = "Evolution de la valence du sentiment du confinement", y="Valence (+/-)",x="dates (par heures)",
subtitle = "Valence par heure",
caption = "\nSource: Data collected by Benavent C. from Twitter's REST API via rtweet"
)
un peu d’analyse des auto-corrélations et des corrélations croisées ou comment analyser les relations de la peine et du bonheur. IL nous faut deux grilles théoriques.
Pour des idées de code :
http://r-statistics.co/Time-Series-Analysis-With-R.html
https://a-little-book-of-r-for-time-series.readthedocs.io/en/latest/src/timeseries.html
#tt <- ts(foo$sentiment,start=c(2020,firstHour),frequency=24*365)
On se concentre sur les 8 facettes de l’émotion telle que conceptualisée par Plutchik (@plutchik_psychoevolutionary_1982), on reprend les définitions en anglais :
et en francais
Elle est mesurée sur la base des textes par l’outil NCR élaborée par Mohammad Saif, pour le français voir.
On peut raisonner en part relative des émotions dans le mesure où l’outil NCR compte les éléments probables de chacune des émotions. Un même texte peut être sujet à plusieurs émotions. Certains ne le seront à aucune et seront donc neutre. La somme des scores d’émotion mesure d’une certaine manière l’expressivité des textes, leur écart à une langue de type administrative qui tente de liquider tout terme expressif et émotionnel. Nous utiliserons cette propriété.
emoevol<-df_nrc %>% group_by(month,day,hour) %>% mutate(n=1) %>%
summarise(anger=mean(anger,na.rm=TRUE),
anticipation=mean(anticipation, na.rm=TRUE),
disgust=mean(disgust, na.rm=TRUE),
fear=mean(fear, na.rm=TRUE),
joy=mean(joy, na.rm=TRUE),
sadness=mean(sadness, na.rm=TRUE),
surprise=mean(surprise, na.rm=TRUE),
trust=mean(trust, na.rm=TRUE),
n=sum(n))
emoevol$date<-paste0("2020","-",emoevol$month,"-",emoevol$day," ",emoevol$hour,":00:00")
emoevol$date2 <- as.POSIXct(strptime(emoevol$date, "%Y-%m-%d %H:%M:%S"))
foo<-emoevol %>% ungroup %>%select(date2, anger,fear,disgust, sadness ,surprise,anticipation,trust, joy )
emocol<-c("red3","orangered1","purple3","royalblue3","chartreuse","olivedrab3","green4","yellow") #en respectant des codes mais il faudra adoucir.
#la distribution des émotions
foo<-melt(foo, id=c("date2"))
#foo$variable2<-factor(foo$variable, ordered = TRUE,levels = c("joy","trust","anticipation","surprise","sadness","disgust","fear","anger"))
ggplot(foo, aes(x=date2,y=value,group=variable))+
geom_line(size=1,aes(color=variable),show.legend = FALSE)+
theme(axis.text.x=element_text(angle = 90, vjust = 0.5))+
theme_minimal()+ stat_smooth(method = "gam", aes(color=variable) )+
labs(title="Les émotions des tweets #ConfinementJour", y="Intensité moyenne (par heure)",x=NULL,caption= "Définitions Plutchik (82) - operationalisation via NRC - lissage GAM:
- la confiance va de l'acceptation à l'admiration
- la peur passe de la timidité à la terreur
- la surprise va de l'incertitude à l'étonnement
- la tristesse passe de la morosité au chagrin
- le dégoût va de l'aversion à la répugnance
- la colère passe de l'agacement à la fureur
- l'anticipation va de l'intérêt à la vigilance
- La joie passe de la sérénité à l'extase
\n \nSource: Data collected by Benavent C. from Twitter's REST API via rtweet")+
facet_wrap(vars(variable),ncol=4)+
scale_color_manual(values=emocol)+ scale_x_datetime(date_breaks = "1 day", labels = scales::label_date_short())
##################
emoevol<-df_nrc %>% group_by(Jour) %>% mutate(n=1) %>%
summarise(anger=mean(anger,na.rm=TRUE),
anticipation=mean(anticipation, na.rm=TRUE),
disgust=mean(disgust, na.rm=TRUE),
fear=mean(fear, na.rm=TRUE),
joy=mean(joy, na.rm=TRUE),
sadness=mean(sadness, na.rm=TRUE),
surprise=mean(surprise, na.rm=TRUE),
trust=mean(trust, na.rm=TRUE),
n=sum(n))
foo<-emoevol %>% ungroup %>%select(Jour, anger,fear,disgust, sadness ,surprise,anticipation,trust, joy )
foo<-melt(foo, id=c("Jour")) %>% filter(Jour<33)
ggplot(foo, aes(x=Jour,y=value,group=variable))+
geom_line(size=1,aes(color=variable),show.legend = FALSE)+
theme(axis.text.x=element_text(angle = 90, vjust = 0.5))+
theme_minimal()+ stat_smooth(method = "loess",size=2, aes(color=variable) )+
labs(title="Les émotions des tweets #ConfinementJour", y="Intensité moyenne (par heure)",x=NULL,caption= "Définitions Plutchik (82) - operationalisation via NRC - lissage GAM:
- la confiance va de l'acceptation à l'admiration
- la peur passe de la timidité à la terreur
- la surprise va de l'incertitude à l'étonnement
- la tristesse passe de la morosité au chagrin
- le dégoût va de l'aversion à la répugnance
- la colère passe de l'agacement à la fureur
- l anticipation va de l'intérêt à la vigilance
- La joie passe de la sérénité à l'extase \n \nSource: Data collected by Benavent C. from Twitter's REST API via rtweet")+ scale_color_manual(values=emocol)
# facet_wrap(vars(variable),ncol=4)+
et sous une autre forme.
emocol<-c("red3","orangered1","purple3","royalblue3","chartreuse","olivedrab3","green4","gold") #ern respectant des codes mais il faudra adoucir.
ggplot(foo, aes(x=Jour,y=value,group=variable))+
geom_area(stat="identity",size=5,aes(fill=variable),show.legend = TRUE, position="stack")+
theme(axis.text.x=element_text(angle = 90, vjust = 0.5))+
theme_minimal()+
labs(title="Les émotions des tweets #ConfinementJour", y="Intensité moyenne (par heure)",x=NULL,caption= "Définitions Plutchik (82) - operationalisation via NRC - lissage GAM:
- la confiance va de l'acceptation à l'admiration
- la peur passe de la timidité à la terreur
- la surprise va de l'incertitude à l'étonnement
- la tristesse passe de la morosité au chagrin
- le dégoût va de l'aversion à la répugnance
- la colère passe de l'agacement à la fureur
- l'anticipation va de l'intérêt à la vigilance
- La joie passe de la sérénité à l'extase
\n \nSource: Data collected by Benavent C. from Twitter's REST API via rtweet")+
scale_fill_manual(values=emocol)
Une représentation moins brute peut être fournie. On va recalculer les score de manière relative en sommant les scores bruts. et en rapportant cette somme au score.
emocol<-c("red3","orangered1","purple3","royalblue3","chartreuse","olivedrab3","green4","gold") #en respectant des codes mais il faudra adoucir.
foo<-emoevol %>% ungroup %>%select(Jour, anger,fear,disgust, sadness ,surprise,anticipation,trust, joy ) %>% filter(Jour<33)
emo<-subset(foo,select=-c(Jour))
emo$tot<-rowSums(emo, na.rm = FALSE, dims = 1)
emo$tot[is.na(emo$tot)]<-0.000001
emo$p_anger<-emo$anger/emo$tot
emo$p_anticipation<-emo$anticipation/emo$tot
emo$p_disgust<-emo$disgust/emo$tot
emo$p_fear<-emo$fear/emo$tot
emo$p_joy<-emo$joy/emo$tot
emo$p_sadness<-emo$sadness/emo$tot
emo$p_surprise<-emo$surprise/emo$tot
emo$p_trust<-emo$trust/emo$tot
foo2<-emo %>%
select(p_anger,p_anticipation,p_disgust, p_fear,p_joy, p_sadness ,p_surprise,p_trust)
date<-foo %>%select(Jour)
foo2<-cbind(date,foo2)
foo2<-melt(foo2, id=c("Jour"))
ggplot(foo2, aes(x=Jour,y=value,group=variable))+
geom_area(stat="identity",size=5,aes(fill=variable),show.legend = TRUE, position="fill")+
theme_minimal()+theme(axis.text.x = element_text(size=11, angle=45))+
labs(title="Spectre des émotions #confinementjour", y="Proportion",x=NULL)+
scale_fill_manual(values=emocol)+
scale_color_manual(values=emocol)
La somme des émotions moyennes, elles peuvent d’additionner car elle ne sont pas exclusive dans les textes ( on peut avoir en même temps de la trisesse et de la joie), représente en quelque sorte l’“émotionnalité” de la production textuelle quelqu’en soit la couleur.
Apres une première montée, une seconde semble s’observer. Est-ce un changement du sentiment moyen dans la population ou l’effet de l’engagement sur le hashtag?
foo3<-emo %>% select(tot)
date<-foo %>%select(Jour)
foo3<-cbind(date,foo3)
ggplot(foo3, aes(x=Jour,y=tot))+
geom_line(stat="identity",size=1,show.legend = TRUE,color="gold2")+
theme_minimal()+theme(axis.text.x = element_text(size=11, angle=45))+
labs(title="Intensité des émotions #confinementjour", subtitle="par heure", y="Somme des émotions",x=NULL)+ geom_smooth(method="loess", color="orange3")
Nos séries sont-elles corrélées ? Si elles le sont de manière instantanée c’est qu’elle partagent une cause commune.
Une structure bifactorielle avec la surprise associée aux deux pôles positifs et négatifs : heureux/malheureux, joyeux/triste …
M1<-subset(df_nrc, select=c( anger,disgust, fear, sadness ,surprise,anticipation,trust,joy))
cor1 <- cor(M1)
library(corrplot)
corrplot.mixed(cor1)
# Maximum Likelihood Factor Analysis
# entering raw data and extracting 3 factors,
# with varimax rotation
fit <- factanal(M1, 2, rotation="promax")
print(fit, digits=2, cutoff=.3, sort=TRUE)
##
## Call:
## factanal(x = M1, factors = 2, rotation = "promax")
##
## Uniquenesses:
## anger disgust fear sadness surprise anticipation
## 0.23 0.55 0.24 0.44 0.53 0.53
## trust joy
## 0.65 0.29
##
## Loadings:
## Factor1 Factor2
## anger 0.90
## disgust 0.69
## fear 0.88
## sadness 0.74
## surprise 0.54
## anticipation 0.69
## trust 0.59
## joy 0.88
##
## Factor1 Factor2
## SS loadings 2.72 1.90
## Proportion Var 0.34 0.24
## Cumulative Var 0.34 0.58
##
## Factor Correlations:
## Factor1 Factor2
## Factor1 1.00 -0.32
## Factor2 -0.32 1.00
##
## Test of the hypothesis that 2 factors are sufficient.
## The chi square statistic is 23228.59 on 13 degrees of freedom.
## The p-value is 0
# plot factor 1 by factor 2
load <- fit$loadings[,1:2]
plot(load,type="n") # set up plot
text(load,labels=names(M1),cex=.7) # add variable names
la tendance
et la corrélation avec le NRC
On va analyser trois groupes de variables : celles liées aux proches ( ami, famille, humains), celles liée à la physiologie (alimentation, corps,sexualité,santé ) et enfin celle liée à la dimension saptiotemporelle.
#library(scales)
foo<-df_nrc %>% group_by(month,day,hour) %>% mutate(n=1) %>% summarise(ami=mean(ami,na.rm=TRUE),famille=mean(famille,na.rm=TRUE),humain=mean(humain,na.rm=TRUE))
foo$date<-paste0("2020","-",foo$month,"-",foo$day," ",foo$hour,":00:00")
foo$date2 <- as.POSIXct(strptime(foo$date, "%Y-%m-%d %H:%M:%S"))
foo<-foo %>% ungroup %>%select(date2,ami, famille, humain )
foo<-melt(foo,id="date2")
emocol<-c("red3","orangered1","olivedrab3", "chartreuse","royalblue3","green4","yellow","purple3") #en respectant des codes mais il faudra adoucir.
ggplot(foo, aes(x=date2,y=value,group=variable))+
geom_line(size=1,show.legend = FALSE,aes(color=variable))+
theme(axis.text.x=element_text(angle = 90, vjust = 0.5))+
theme_minimal()+ stat_smooth(method = "gam" , aes(color=variable))+
labs(title="Les thématiques des proches #ConfinementJour", y="Intensité moyenne (par heure)",x=NULL,caption= " \nSource: Data collected by Benavent C. \n from Twitter's REST API via rtweet \n and processed with Liwc & tidyverse")+
scale_color_manual(values=emocol)+facet_wrap(vars(variable),ncol=3)+
scale_x_datetime(date_breaks = "1 day", labels = scales::label_date_short())
foo<-df_nrc %>% group_by(month,day,hour) %>% mutate(n=1) %>% summarise(alimentation=mean(alimentation,na.rm=TRUE),sexualité=mean(sexualité,na.rm=TRUE),santé=mean(santé,na.rm=TRUE),corps=mean(corps,na.rm=TRUE))
foo$date<-paste0("2020","-",foo$month,"-",foo$day," ",foo$hour,":00:00")
foo$date2 <- as.POSIXct(strptime(foo$date, "%Y-%m-%d %H:%M:%S"))
foo<-foo %>% ungroup %>%select(date2, alimentation,sexualité, santé,corps )
foo<-melt(foo,id="date2")
emocol<-c("green4","red3","royalblue2","orangered1","purple3","chartreuse","olivedrab3","yellow") #en respectant des codes mais il faudra adoucir.
ggplot(foo, aes(x=date2,y=value,group=variable))+
geom_line(size=1,show.legend = FALSE,aes(color=variable))+
theme(axis.text.x=element_text(angle = 45))+
theme_minimal()+ stat_smooth(method = "gam" , aes(color=variable))+
labs(title="Thématiques alimentation, sexualité, santé des tweets #ConfinementJour", y="Intensité moyenne (par heure)",x=NULL,caption= " \nSource: Data collected by Benavent C. \n from Twitter's REST API via rtweet \n and processed with Liwc & tidyverse")+
scale_color_manual(values=emocol)+facet_wrap(vars(variable),ncol=2)+ scale_x_datetime(date_breaks = "1 day", labels = scales::label_date_short())
foo<-df_nrc %>% group_by(month, day,hour) %>% mutate(n=1) %>% summarise(sentir=mean(sentir,na.rm=TRUE),voir=mean(voir,na.rm=TRUE),entendre=mean(entendre,na.rm=TRUE),mouvement=mean(corps,na.rm=TRUE),espace=mean(espace,na.rm=TRUE),temps=mean(temps,na.rm=TRUE))
foo$date<-paste0("2020","-",foo$month,"-",foo$day," ",foo$hour,":00:00")
foo$date2 <- as.POSIXct(strptime(foo$date, "%Y-%m-%d %H:%M:%S"))
foo<-foo %>% ungroup %>%select(date2, mouvement, espace, temps)
foo<-melt(foo,id="date2")
emocol<-c("green4","red3","royalblue2","orangered1","purple3","chartreuse","olivedrab3","yellow") #en respectant des codes mais il faudra adoucir.
ggplot(foo, aes(x=date2,y=value,group=variable))+
geom_line(size=1,show.legend = FALSE,aes(color=variable))+
theme(axis.text.x=element_text(angle = 45))+
theme_minimal()+ stat_smooth(method = "gam" , aes(color=variable))+
labs(title="Thématiques alimentation, sexualité, santé des tweets #ConfinementJour", y="Intensité moyenne (par heure)",x=NULL,caption= " \nSource: Data collected by Benavent C. \n from Twitter's REST API via rtweet \n and processed with Liwc & tidyverse")+
scale_color_manual(values=emocol)+facet_wrap(vars(variable),ncol=3)+ scale_x_datetime(date_breaks = "1 day", labels = scales::label_date_short())
##les topics par jour
On exploite ici les ressources du #Liwc pour apprécier la nature de l’expérience partagée sur #confinement jour.
on y examine
foo<-df_nrc %>% group_by(Jour) %>% mutate(n=1) %>% summarise(sentir=mean(sentir,na.rm=TRUE),voir=mean(voir,na.rm=TRUE),entendre=mean(entendre,na.rm=TRUE),mouvement=mean(corps,na.rm=TRUE),espace=mean(espace,na.rm=TRUE),temps=mean(temps,na.rm=TRUE))
foo<-foo %>% ungroup %>%select(Jour, mouvement, espace, temps)
foo<-melt(foo,id="Jour") %>%filter(Jour<33)
emocol<-c("green4","firebrick","royalblue3","orangered1","purple3","chartreuse","olivedrab3","yellow") #en respectant des codes mais il faudra adoucir.
ggplot(foo, aes(x=Jour,y=value,group=variable))+
geom_line(size=1,show.legend = FALSE,aes(color=variable))+
theme(axis.text.x=element_text(angle = 45))+
theme_minimal()+ stat_smooth(method = "gam" , aes(color=variable),size=1.5)+
labs(title="Thématiques du temps, de l'espace et du mouvement -tweets #ConfinementJour", y="Intensité moyenne (par heure)",x=NULL,caption= " \nSource: Data collected by Benavent C. \n from Twitter's REST API via rtweet \n and processed with Liwc & tidyverse")+
scale_color_manual(values=emocol)+facet_wrap(vars(variable),ncol=3)
#l'organique
foo<- df_nrc%>% group_by(Jour) %>% mutate(n=1) %>% summarise(alimentation=mean(alimentation,na.rm=TRUE),sexualité=mean(sexualité,na.rm=TRUE),santé=mean(santé,na.rm=TRUE),corps=mean(corps,na.rm=TRUE))
foo<-foo %>% ungroup %>%select(Jour, alimentation,sexualité, santé,corps )
foo<-melt(foo,id="Jour")%>%filter(Jour<33)
emocol<-c("green4","red3","royalblue2","orangered1","purple3","chartreuse","olivedrab3","yellow") #en respectant des codes mais il faudra adoucir.
ggplot(foo, aes(x=Jour,y=value,group=variable))+
geom_line(size=1,show.legend = FALSE,aes(color=variable))+
theme(axis.text.x=element_text(angle = 45))+
theme_minimal()+ stat_smooth(method = "gam" , aes(color=variable))+
labs(title="Thématiques : alimentation, sexualité, santé des tweets #ConfinementJour", y="Intensité moyenne (par heure)",x=NULL,caption= " \nSource: Data collected by Benavent C. \n from Twitter's REST API via rtweet \n and processed with Liwc & tidyverse")+
scale_color_manual(values=emocol)+facet_wrap(vars(variable),ncol=4)
# l’analyse des résultats du lexicoder
Les indicateurs de sentiment construits sur des dictionnaires et a fortiori traduits posent des questions de validité de mesure : - validité de contenu - validité convergente - validité discriminante - fiabilité et consistance interne - sensibilité
Les différentes mesures de sentiment vont-elle dans le même sens?
Faut-il les combiner au travers d’un modèle factoriel?
Comment conserver les nuances?
Une approche en terme de correlations à trois niveaux : l’unité de texte et son évolution dans le temps; l’echelle de l’heure, l’échelle du jour.
#cor
#cor
#cor
Une approche en terme de reliability et finalement ce sont les items d’un score. une approche factorielle.
l’analyse simple des corrélation montre une faible consistance
r_sent<-subset(df_nrc, select=c( negative,émonég,positive, émopos))
cor2 <- cor(r_sent)
corrplot.mixed(cor2)
Regardons les relations entre émotions et expérience via https://jokergoo.github.io/ComplexHeatmap-reference/book/a-single-heatmap.html
Il faut optimiser pour aussi monter les évolutions.
Faire un gif jour par jour?
M1<-subset(df_nrc, select=c(negative,anger,disgust, fear, sadness,surprise,anticipation,trust,joy,positive))
M2<-subset(df_nrc, select=c( alimentation,sexualité, santé,corps,ami, famille, humain))
cor2 <- cor(M2)
library(corrplot)
corrplot.mixed(cor2, order = "hclust", addrect = 2)
# Maximum Likelihood Factor Analysis
# entering raw data and extracting 3 factors,
# with oblimin(promax) rotation - factors could be correlated
fit <- factanal(M1,2, rotation="promax")
print(fit, digits=2, cutoff=.3, sort=TRUE)
##
## Call:
## factanal(x = M1, factors = 2, rotation = "promax")
##
## Uniquenesses:
## negative anger disgust fear sadness surprise
## 0.21 0.28 0.51 0.26 0.38 0.61
## anticipation trust joy positive
## 0.57 0.55 0.30 0.36
##
## Loadings:
## Factor1 Factor2
## negative 0.89
## anger 0.86
## disgust 0.72
## fear 0.87
## sadness 0.78
## anticipation 0.65
## trust 0.67
## joy 0.86
## positive 0.81
## surprise 0.48
##
## Factor1 Factor2
## SS loadings 3.52 2.51
## Proportion Var 0.35 0.25
## Cumulative Var 0.35 0.60
##
## Factor Correlations:
## Factor1 Factor2
## Factor1 1.00 -0.29
## Factor2 -0.29 1.00
##
## Test of the hypothesis that 2 factors are sufficient.
## The chi square statistic is 85343.51 on 26 degrees of freedom.
## The p-value is 0
# plot factor 1 by factor 2
load <- fit$loadings[,1:2]
plot(load,type="n") # set up plot
text(load,labels=names(M1),cex=.7) # add variable names
Jour2 <- c(2,8,20)
for (val in Jour2) {
M1<-df_nrc %>% filter (Jour ==val) %>% select(negative,anger,disgust, fear, sadness,surprise,anticipation,trust,joy,positive)
M2<-df_nrc %>% filter (Jour ==val) %>% select( alimentation,sexualité, santé,corps,ami, famille, humain)
cor3<-cor(x=M1,y=M2)
cor3 <- melt(cor3)
g<-ggplot(data = cor3, aes(x=Var1, y=Var2, fill=value)) +
geom_tile()+ labs(title="Corrélations entre les domaines de l'expérience et les émotions",x="Sentiments", y="Domaines")+
scale_fill_gradient2(low = "blue", high = "red", mid = "white",midpoint = 0, limit = c(-0.3,0.3), space = "Lab",
name="Pearson\nCorrelation")
g
}
val<-20
M1<-df_nrc %>% filter (Jour ==val) %>% select(negative,anger,disgust, fear, sadness,surprise,anticipation,trust,joy,positive)
M2<-df_nrc %>% filter (Jour ==val) %>% select( alimentation,sexualité, santé,corps,ami, famille, humain)
cor3<-cor(x=M1,y=M2)
cor3 <- melt(cor3)
g<-ggplot(data = cor3, aes(x=Var1, y=Var2, fill=value)) +
geom_tile()+ labs(title="Corrélations entre les domaines de l'expérience et les émotions",x="Sentiments", y="Domaines")+
scale_fill_gradient2(low = "blue", high = "red", mid = "white",midpoint = 0, limit = c(-0.3,0.3), space = "Lab",
name="Pearson\nCorrelation")
g