Résumé : Cet article a pour but par des techniques de tex-mining d’explorer les différences de production langagière dans différentes classes d’hôtel de l’espace de la pôlynésie françaises. Les différences observées contribuent à une réflexion sur la production de contenu dans les plateformes alimentée par le crowdsourcing et aux méthodes à employer pour exploiter à fin d’étude ces corpus importants.
mots-clés : textmining, Analyse de sentiment, Hospitalité, Hôtel, UGC, Avis, Note, Marketing, Consommateur, Plateforme
Abstract : The purpose of this article is to explore the differences in language production in different hotel classes in the French polynesia space through tex-mining techniques. The differences observed contribute to a crowdsourced reflection on the production of content in plateforms and the methods to be used to exploit these important corpuses for study purposes.
Keyword : Textmining,Sentiment Analysis, Hospitality, UGC, Rating and reviews, Marketing, Consumer, Platform, LDA, LSA, TSNE
Les plateformes de contenus collaboratives sont désormais bien installées dans le paysage et jouent un rôle désormais central dans l’économie du tourisme. Dans le secteur de l’hôtellerie, TripAdvisor par l’étendue de sa couverture et la densité des commentaires, s’est taillé une place de choix. Ce n’est pas la seule, des plateformes comme Booking.com ou Airbnb sont des acteurs de premier plan qui concentrent une grande part des réservations. ( des chiffres à trouver)
La particularité de ces dispositifs est que même si la plateforme détient des outils pour orienter la nature et la tonalité des contenus ( formulaires, boutons), qu’elle en maitrise la projection par ses outils de classement, de tri, de recommandation, ce sont les flux de populations qui fabriquent collectivement le contenu.
On peut dès lors faire l’hypothèse d’une segmentation de ces populations. Dans une forme très simplifiée, le modèle est celui de deux populations qui diffèrent en capital mais aussi en compétences. Les mieux dotés savent mieux parler de leur sujet que les autres, et valorisent ainsi mieux leur capital. Une telle situation devrait conduire à une certaine polarisation du marché.
C’est cette hypothèse qu’on souhaite explorer dans cette communication en comparant systématiquement la production langagière des populations de différentes catégories d’hôtels. Ceux-ci ne diffèrent pas seulement pas leurs standings et leurs équipents mais aussi par la composition de leur clientèle qui participent à l’expériences des hotes. Etre auprès de stars n’a pas la même valeur que de partager un hotel des des toxicos et des prostituées? Dans allez dans cette polarité imaginaire, on peut cependant considérer que les différences des visiteurs de hotels familiaux et des hotels de luxe peeuvent ep^tre marqué dans la production de commentaire. par les sujet et par le style.
en polynésie. Ce terrain présente des avantages : c’est une région isolée du monde qu’on peut bien circonscrire qui s’étend sur une vaste étendue, le tourisme y est l’activité la plus importante représenat 10% du PIB (et 300 000 personnes), la segmentation du marché est prononcé avec des hotels de très grand luxe - le Brando à plusieurs milliers euros la nuit, et de l’hébergement familial (les pensions). Le potentiel représente 220 établissements et 4000 lits (?à vérifier)
En comparant systématiquement ce que les gens disent et comment ils le disent, nous souhaitons tester l’hypothèse d’une certaine polarisation. Là ont sont les ressources, elles sont aussi langagière, ceux qui fréquentent les établissements plus luxeurx seraient aussi, en moynne, ceux qui en savent parler le mieux, à la qualité de la prestation, de l’expérience, s’ajoute la qualité de l’expression.
Elle est modérée par une logique de l’effort de de l’engagement. On s’attend que dans les établissement les plus modestes, de moindres ressources conduisent à exploiter plus les ressources disponibles, dont celles de la parole des clients.
Prendre en compte les qualités discursives des clients dans les plateformes d’avis, c’est non seulement contribuer à une sociologie du langage, mais aussi de l’intimité du fonctionnement des plateformes, et de l’universalité des mécanismes de renforcement des inégalités. Dans un monde collaboratif, la structuration de ce monde dépend largement de la capacité à maitriser le langage. Elle s’inscrit dans une perspective dont Šuster (2015) donne un excellent exemple en étudiant la qualité du langage dans Wow et en le comparant à la langue standard ou plus spécificiquement Hu and Chen (2016) dans le domaines de l’hotellerie où le même type d’indicateur est employé pour modéliser le “helpfullness” des avis de consommateurs.
notre perspective est celle de la production et l’hypothèse que nous souhations tester est qu’au sein d’une population de contributeurs, on peut distinguer des différences dans la qualité de la production, des différences sociales.
Si l’hypthèse passe le test empirique, nous aurions la démonstration que la qualité de la production peut être controlées : soit par des politique d’empowerment qui se concentrant sur les moins habiles leur proposent des méthodes d’amélioration de la qualité de leur production ( ne serait-ce que par des modèles types), où par une politique de selection.(mise en avant des contenus scorés comme les plus lisibles, les plus riches ou les plus pertinents)
Le point de départ de notre analyse est une pratique désormais institutionnalisée celle du crowdsourcing comme pratique et comme système. Nous aurons à en donner une synthèse des travaux et des avancées.
Les Notes et avis font désormais l’objet d’une littérature très abondante, nous aurons donc à en donner un synthèse qui rappele les principaux concepts, et les principaux résultats empiriques.
Si le point de vue individuel, micro economique et psychologique est favorisé, nous devons rester attentif aux mouvement des populations, les notions de l’écologie des populations peuvent à ce propos être utiles. La production de contenu est une affaire collective, le résultat de la confrontation des populations et des flux qu’elles génèrent. La fameuse expérience de facebook (Kramer, Guillory, and Hancock (2014) ) sur la contagion des émotions en est en quelque sorte le modèle fondateur : en manipulant le feed de près de 700 000 comptes par un contrôle des contenus positifs et négatifs, les chercheurs de facebook démontrent qu’on peut affecter la production des participants à la fois en volume et en qualité, ne serait-ce que de manière marginale.
Les comparateurs, et a fortiori les plateformes de réservations s’appuient sur une ressources précieuses : les notes et les commentaires de leurs clients. Elle participent à ce mouvement du crowd sourcing dont Jeff Howes1 a popularisé l’émergence.
Une vaste litérature s’est constituée et on dispose de nombreuses synthèses : (???)
Le crowdsourding doit être abordé comme un processus dont le schéma général2 est représenté dans la figure 1. Les contenus produits dépendent naturellement de l’expérience vécue par les consommateurs qui les motivent plus ou à moins à partager leur émotion (1) dont une partie s’exprime sur les plateformes (2).
Le degré de participation est une question importante, on réalise désormais qu’il est généralement faible, et dépend largement de l’effort requis par la tâche (pour 10 vue un like, pour 10 like, un commentaire). Ce contenu cependant peut être troublé par des informations mensongères (3) produites par les gérants des établissements pour corriger une fiche qu’ils trouveraient pas assez attractive, d’agences spécialisées dans les techniques de marketing furtif, de trolls (ref) ou de toutes autres formes de hacking.
Cette production fait l’objet d’une part de modération de plus en plus sévère; (elle occupe 300 personnes chez tripadvisor qui accumule 700 000 000 d’avis.voir.
Ce contenu est exposé aux travers des requêtes de manière organisée généralement pas des tri ( par prix, notes…) ou de manière plus sophistiquée par des moteurs de recommandation. Elle permettent de classer(), de trier(), de recommander(). L’agrégation des contenus peut suivre des règles particulières, par exemple présenter en parallèle des contenus positifs et négatifs, ou les classer selon un critère calculé de pertinence.
Ces informations, renforcées ou non par la réaction de tièrces parties, possèdent pour les consommateurs un degré plus ou important de crédibilité et de validité (6). C’est ce qui affecte les décisions de choix (8) ce qui en retour à la fois affecte le contenu (quand les sujets prennent la décision de le partagé) mais aussi l’expérience qu’ils vont éprouver.
On est donc fasse à un processus technico-social, qui se constitue dans une boucle de feed back doublement contrôlée par l’engagement des acteurs, les affordances et les contrôles du système. Il convidendra naturellement d’être critiques quant auxc résultats observables et de s’interroger sur la validité de telles informations, même s’il semble nécessaire de s’intéresser aux moyens qu’on peut employer pour les rendre intelligibles et candidates pour tester les hypothèses de la science.
Si l’uGC est potentiellement un facteur d’influences des choix, il est aussi un produit dont les consommateurs sont les acteurs. Il devient aujourd’hui important de comprendre quels sont les processus qui en régule la production.
Une littérature étendue qui converge vers l’hypothèse de la binarisation du jugement. des affordances, des adaptations…..
commence avec les notes surtout dans les films (années 2002)
Alimentée par une production importante dans le champs de l’informatique et de la linguistique, les application de l’analyse du sentiment et d’autres techniques moderne d’analyse textuelle émerge au virage des années 2007 avec des travaux spécifique tels ceux de Pekar and Shiyan Ou (2008) . émergence plus récente dans la littérature Si et marketing avec quelques exceptions comme
la question des notes. Les notes se sont tuées par elle même et deviennent binaire comme Ordenes et al. (2017) en rend compte précisement. Un vieil article de one monday sur la signification du like avait parfaitement posé le problème ( Eranti and Lonkila (2015) ), ce qui importe est quel rapport social des noteurs établissent avec le système de notation.
Des plateformes comme TripAdvisor ne sont pas que des aggrégateurs de contenu, ce sont des espaces dans lesquelles les populations interéagissent : les hôteliers, leurs hôtes, touristes locaux ou internationaux. Et ce qu’elles offrent, c’est le produit de ces interations.
L’illustration de ces interactions est une analyse des éffets de sélection remarquable : Les déçus ne revienennent pas et s’ils donnent un avis c’est por se plaindre ou se venger, il ne le feront qu’une fois. Les clients heureux et motivé pour partager leurs émotions on toute les chance de rétirer l’expérience et le commentaire de l’expérience. Ils publierons plusieurs fois. Mêmle si ces deux population sont égales en importance, on comprend qu’on trouvera 2 ou 3 fois plus de commentaires positifs. Alors que les populations sont en proportion égales, l’une d’elle contribue de manière très inégale à la population des commentaires. On ne peut exclure d’autre processus du même ordre et on doit considérer que le produit des populations n’en reflète pas la composition.
Un aspect peu étudié est l’hétérogéneité des populations qui participent à la production des contenus même si on notera (???) (???) et (???). Cette hétérogénéité a plusieurs sources :
Dans le cas de l’hôtellerie des compétences inégalement distribuées notamment dans le marketing :
L’hypothèse générale que l’on va tester est de savoir si le langage et les sentiments exprimés diffèrent d’une catégorie d’hôtel à l’autre. Plusieurs arguments l’animent :
En comparant sur différents critères
l’objectif est de réaliser une analyse du sentiment et de comparer les production textuelles des population de clients des hotels de luxe et des hotels populaires(il faut des reférences pour cette catégorisation).
On utilisant les ressources de utilisation de quanteda ((???)), tidyverse, cleanNPL …
Ces approches sont alimentée largement par les computer siences et la linguistique. Cependant le marketing et les sciences du consommateur commencent à s’en approcher, on lira avec attention Humphreys and Wang (2018) à ce sujet.
L’objectif est de produire un certains nombre d’indicateurs pour comparer de manière systématique les différentes catégories de critères. Le corpus initial a été constitué par un essai de scrapping des fiches “avis de consommateur” du site tripadvisor. 12500 contenus uniques ont été moisonnés, on les associe aux hôtels et à leurs caractéristiques qui font l’objet de ces commentaires. On a employé Rvest, le code est disponible sur demande, il est en cours d’amélioration.
Le nombre de nouveaux commentaire par année est la suivante (2018 est sur 6 mois, on se gardera de conclure à un renversement de tendance, mais plus à une stabilisation autour des 1800 par mois). Par la suite on regroupe les années avant 2011 (inclus) dans une catégorie 2011.
evol <- with(dupBase, table(year2))
evol<-as.data.frame(evol)
evol$year2<-as.factor(evol$year2)
ggplot(evol,aes(x=year2, y=Freq))+geom_bar(stat="identity")+theme_minimal()
un champs texte et un dataframe de variables complémentaires constitue le Corpus (au sens de quanteda)
Corpus<-corpus(dupBase,text_field="text") #corpus de base qui sera filtré
la tokenisation consiste à definir les unités de base. Nous retiendrons les mots et certains ngrams, mais ce peuvent être des syllabes, des ngrams, des phrases, des paragraphe, voir toute autre unité de langage qu’on trouve pertinente. Un document est constitué d’unités qui pourront être qualifiées en fonction de leur valeur lexicale ou syntaxique.
On en profite pour nettoyer le texte de la ponctuation, des nombres, des symboles, des séparateurs, et des stop words. La fonction kwic
permet d’identifier les textes associés à un terme cible. C’est un bon moyen de comprendre qualitativement ce dont on parle. Un moyen simple de remettre les mots dans leur contexte.
toks <- tokens(Corpus, what="word",remove_punct = TRUE,remove_numbers = TRUE,
remove_symbols = TRUE, remove_separators = TRUE,
remove_twitter = TRUE, remove_hyphens = TRUE, remove_url = TRUE,
ngrams = 1:2, skip = 0L, concatenator = "_")
toks<- tokens_remove(toks, stopwords('french'), valuetype = 'fixed', padding = TRUE)
#key words
kw <- kwic(toks, pattern = 'Moorea')
head(kw, 7)
##
## [90, 4] Week end a | moorea |
## [90, 47] ptits spot sympa | Moorea |
## [311, 10] coupe d'Europe France Portugal | Moorea |
## [312, 10] Belle plage lagon | Moorea |
## [349, 6] Fuyez pires malhonnetes | Moorea |
## [713, 52] plus semaine | Moorea |
## [716, 86] d'une nuit avant d'aller | Moorea |
##
## Séjour agréable passée
## aucun Plus Week_end end_a
## vu résultat
## super beau verrez
## louais maison
## voyage n'oublierai
## Procurent précieux services
Cette solution est d’autant plus utile qu’elle propose une fonction qui calcule la vraisemblance de certains bi ou trigrammes d’être en fait des expressions composées qu’on tiendra pour un seul token, par la technique de la collocation.
La dernière ligne de code permet d’ajouter au fichier des tokens les multigrammes (mots composés) après avoir pris la décision de choisir le critère lambda supérieur à supérieur à 7. Nos unités sont désormais constituées de mots et d’une sélection d’expressions composées.
col <- toks %>%
tokens_remove(c(" ")) %>%
textstat_collocations(min_count = 100,size=2, tolower = FALSE)
head(col,8)
## collocation count count_nested length lambda z
## 1 Bora Bora 2444 0 2 6.671647 194.7801
## 2 petit déjeuner 2116 0 2 8.812591 159.8322
## 3 et_nous nous_avons 1218 0 2 6.378895 145.7850
## 4 très bien 1501 0 2 4.432655 137.8136
## 5 il_y y_a 920 0 2 7.856591 134.1626
## 6 Il_y y_a 1027 0 2 8.567936 129.3158
## 7 bungalow_sur sur_pilotis 822 0 2 8.352632 127.9084
## 8 Nous_avons avons_passé 1061 0 2 6.356647 125.7267
toks <- tokens_compound(toks, pattern = col[col$lambda > 7])
Dénommé ainsi comme évolution des “documents terms matrix” (dtm)" dans le style de tm
le package historique du traitement textuel. Il est le coeur de l’analyse textuelle en croisant les documents et ses éléments constitutifs.
Dans notre cas nous disposons de 11378 documents et de 24911 features. Ce tableau est naturellement vide avec un taux de sparcity de 0.9972 %.
On peut analyser de manière brute la distribution des termes. Les plus fréquent ne sont pas les plus informatifs et il faudra filtrer, c’est ce qui est fait dans la partie droite de la figure en ne retenant que ceux dont la fréquence est inférieure à 6200 ce qui élimine les “stop word” ( article, pronoms, conjonction).
df<-dfm(Corpus)
ndoc(df)
## [1] 11378
nfeat(df)
## [1] 24911
sparsity(df)
## [1] 0.9971791
cf<-as.data.frame(topfeatures(df, n = 80, decreasing = TRUE, scheme = c("count","docfreq"), groups = NULL))
cf$term<-row.names(cf)
cf$frequence<-cf[,1]
g05<-ggplot(cf,aes(x=reorder(term,frequence),y=frequence))+geom_point()+coord_flip()+theme_minimal()+theme(text = element_text(size=9))+ labs(title = "Fréquences des termes (par ordre décroissant", x="terms", y="fréquence")
cf<-subset(cf, frequence<6200)
g06<-ggplot(cf,aes(x=reorder(term,frequence),y=frequence))+geom_point()+coord_flip()+theme_minimal()+theme(text = element_text(size=9))+ labs(title = "Fréquences des termes (par ordre décroissant", x="terms", y="fréquence")
grid.arrange(g05,g06,ncol=2) #utilise gridextra
Quelques éléments de volumétrie complémentaires permettent de bien saisir les données. On les obtient en examinant la distribution de la longueur des avis en nombre de caractères. On compare par archipel et classe de prix et on observe des différences substantielles.
Nous avons besoin d’indicateurs de
Leur choix, leur définition et leur mise en oeuvre sont développés dans les sections suivantes.
Pour la lisibilité 4 indicateurs sont adoptés les deux premiers sont les unités quantitaives élémentaires * La longueur moyenne de la phrase qui indique son degré d’élaboration.(ie: sais pas; je ne sais pas) * Le nombre de syllabes par mot qui indique la fréquence de mots complexes.(ie : beau, exceptionnel) * L’indice ARI (Senter (1967) ) * L’indice de coleman (Coleman and Liau (1975) )
Ce sont donc des mots court 95% inférieurs à deux syllabes. Pour une référence Hug (2004), avec un corpus du journal le monde (réputé à la lecture exigeante), obtient un ordre de grandeur de 12 à 20 mots par phrase selon les articles, et de 3.3 à 3.7 syllabe par mot. On a donc globalement un langage simple mais peut être aussi sophistiqué que le monde dans une petite partie du corpus.
Les deux autres peuvent difficilement être rapportés au normes habituelles compte tenu de la nature du texte (ie : l’indice de Coleman de 12 correspond au niveau d’un lycéen), il semble même souligné une certaine illisibilité qui vient propablement non pas de la complexité, mais de la maladresse des de la rédaction des avis.
read<- textstat_readability(Corpus, measure = c("ARI","Coleman", "meanSentenceLength", "meanWordSyllables"),
remove_hyphens = TRUE, min_sentence_length = 0, max_sentence_length = 2000,
intermediate = FALSE)
dupBase2<-cbind(dupBase,read)
g05<-ggplot(data = dupBase2, aes(x=Coleman))+geom_histogram(fill="grey")+theme_minimal()
g06<-ggplot(data = dupBase2, aes(x=ARI))+geom_histogram(fill="grey")+theme_minimal()+xlim(-10,50)
g07<-ggplot(data = dupBase2, aes(x=meanWordSyllables))+geom_histogram(fill="grey")+theme_minimal()+xlim(0,3)
g08<-ggplot(data = dupBase2, aes(x=meanSentenceLength))+geom_histogram(fill="grey")+theme_minimal()+xlim(0,50)
grid.arrange(g05,g06, g07,g08,nrow=2) #utilise gridextra
On peut en retracer l’évolution
read2<- aggregate(cbind(Coleman,ARI,meanWordSyllables,meanSentenceLength,nbcar)~year, data=dupBase2,FUN="mean")
read2<-melt(read2)
g09<-ggplot(read2, aes(x=year, y=value, group=variable))+geom_line(size=2,color="lightblue")+facet_grid(variable~.,scale="free")+theme_minimal()
g09
Le comptage des mots ne prends pas en compte leur signification, pas même le lexique. Un mot en deux syllabes comme “apax” (mot unique d’un texte) est plus rare que “cycas” (plante) et bien plus rare que “ara” (perroquet). C’est ce que poursuit l’analyse de la diversité lexicale.
la fonction textstat_lexdiv
s’appuie sur Tweedie and Baayen (1998)
leurs définitions sont données ici et un exemple utilisation. on lira Hug (2004).
les indices de variété lexicale de quanteda que l’on utilise sont le * Maas : * CTTR : Carroll’s Corrected TTR: V/racine(2N) * C : Herdan’s C sometimes referred to as LogTTR):C=logV/logN
c’est au Maas auquel on se se référera. Il est considéré en effet comme un des plus adapté, et indépendant de la taille du texte. Le notre correspond aux plages d’usages habituels.Il faudrait s’assurer que le passage d’une écriture manuscrite (le cas des tests traditionnels) à une écriture “tapuscrite” ne change pas la nature de ces indicateurs.
dfmlex<-dfm(toks, tolower = TRUE,stem=TRUE)
lexdiv <- textstat_lexdiv(dfmlex) #c est tres tres long long aussi
tail(lexdiv, 5)
## document TTR C R CTTR U S
## 11374 31014 0.7956989 0.9495798 7.673443 5.425943 39.04158 0.9236107
## 11375 31054 0.7659574 0.9413138 7.426233 5.251140 33.62167 0.9110110
## 11376 31055 0.8125000 0.9500733 6.500000 4.596194 36.17662 0.9133712
## 11377 31056 0.6923077 0.9184801 6.604194 4.669871 24.03145 0.8735454
## 11378 31057 0.7313433 0.9361203 8.465911 5.986303 33.29863 0.9125403
## K D Vm Maas lgV0 lgeV0
## 11374 465.9498 0.03623188 0.1818831 0.1600429 5.961980 13.72797
## 11375 679.0403 0.05788149 0.2324116 0.1724608 5.502675 12.67038
## 11376 483.3984 0.03323413 0.1706138 0.1662593 5.499538 12.66315
## 11377 790.9673 0.06886447 0.2514433 0.2039905 4.549911 10.47656
## 11378 667.1865 0.05970149 0.2377279 0.1732953 5.662042 13.03733
dupBase3<-cbind(dupBase2,lexdiv)
lex<-subset(dupBase3,select=c(document,Prix_classe,Ile,Archipel,NbChambres,year,C,CTTR,Maas))
g10<-ggplot(lex,aes(x=Maas))+geom_histogram()+theme_minimal()
lex1<-aggregate(Maas~Ile,data=lex,FUN=mean)
g12<-ggplot(lex1, aes(x = reorder(Ile,Maas), y = Maas)) +theme_minimal()+
geom_point() +
scale_y_continuous(limits = c(0.2,0.4), breaks = c(seq(0.2,0.4, .05))) +
xlab(NULL) +
ylab("C") +
theme(axis.text.x = element_text(angle = 0, hjust = 1, size=7),axis.text.y = element_text(size=8))+
coord_flip()+labs(title="Diversité lexicale - par Ile")+ylim(0.1,0.2)
grid.arrange(g10,g12,ncol=2) #utilise gridextra
On peut en suivre l’évolution au cours du temps. celle-ci semble stable mais on s’interroge sur 2018. Les péiodes avant 2011 ont du voir une très forte évolution, il est possible que dans la période le langage se soit normé et s’est réduit en terme de diversité. C’est une hypothèse à explorer : celle de la normativité progressive du langage sur les plateformes sociales. On y apprend des formules, un style de dégage, le langage devient plus lisse et se contente de légères variations autour de conventions pour signaler ses différences. La spontanéité cède le pas aux formules.
divx2<- aggregate(cbind(C,CTTR,Maas)~year, data=lex,FUN="mean")
divx2<-melt(divx2)
g13<-ggplot(divx2, aes(x=year, y=value, group=variable))+geom_line(size=2,color="lightblue")+facet_grid(variable~.,scale="free")+theme_minimal()
g13
La part relative des adjectifs, des verbes, des noms propres et des noms communs peut être un bon moyen de repérer des styles distincts. Une méthode de Part of Speech (PoS) est employée pour annoter chaque mot du corpus avec un étiquettage morpho-syntaxique. On emploie cleanNLP
à cette fin. Il a été crée par Arnold (2017)
Les noms communs dominent largement, avec les déterminants et les ADP. Cette dominance relève peut-être d’un langage descriptif qui s’attache à décrire les objets du discours. Les verbes sont plus fréquents que les adjectifs.
Pour améliorer l’analyse il faudrait des distributions types de la langue française fondées sur des corpus de références caractéristiques (littérature, presse, littérature populaire , autres…).
L’analyse de la langue ne peut se réduire à l’analyse d’un corpus. Elle ne peut être que comparative. Une langue vernaculaire, contre une langue véhiculaire ou trop souvent la langue légitime que consacrent les académies.
text<-dupBase3$text
#on appele la ressource dictionnaire
cnlp_init_udpipe(model_name = "french")
#on annote le texte
obj <- cnlp_annotate(text, as_strings = TRUE) #plutot long aussi des minutes voir par diz
#on extrait le vocabulaire
Vocab<-cnlp_get_token(obj)
Table <- with(Vocab, table(upos))
#on transforme en dataframe
ling<-as.data.frame(Table)
#et on jette un coup d'oeil
g1<-ggplot(ling,aes(x=reorder(upos,Freq),y=Freq))+geom_point()+coord_flip()+theme_minimal()+theme(text = element_text(size=9))
g1
Regardons si les styles, du point de vie de leur composition morphosyntaxique varient selon les iles. Ces variations sont modestes on remarquera une différence du côté des iles australes.
Vocab$uADJ<-0
Vocab$uVERB<-0
Vocab$uNOUN<-0
Vocab$uADV<-0
Vocab$uELSE<-0
Vocab$uADJ[Vocab$upos=="ADJ"]<-1
Vocab$uVERB[Vocab$upos=="VERB"]<-1
Vocab$uNOUN[Vocab$upos=="NOUN"]<-1
Vocab$uADV[Vocab$upos=="ADV"]<-1
Vocab$uELSE[Vocab$upos!="ADV" & Vocab$upos!="NOUN" & Vocab$upos!="VERB" & Vocab$upos!="ADJ"]<-1
Vocab$id<-as.factor(Vocab$id)
syntax<- aggregate(cbind(uADJ,uVERB,uNOUN,uADV,uELSE)~id, data=Vocab,FUN="sum")
syntax$sum<-syntax$uADJ+syntax$uVERB+syntax$uNOUN+syntax$uADV+syntax$uELSE
syntax$uADJ<- syntax$uADJ/syntax$sum
syntax$uVERB<-syntax$uVERB/syntax$sum
syntax$uNOUN<-syntax$uNOUN/syntax$sum
syntax$uADV<-syntax$uADV/syntax$sum
syntax$uELSE<-syntax$uELSE/syntax$sum
dupBase4<-cbind(dupBase3,syntax)
Ag<- aggregate(cbind(uADJ,uVERB,uNOUN,uADV,uELSE) ~ Ile, data=dupBase4, FUN=mean)
Ag<-melt(Ag)
g4<-ggplot(Ag,aes(x=reorder(Ile,value),y=value,group= variable))+geom_line(stat="identity",aes(color=variable),size=2) +coord_flip()+scale_color_brewer(palette = "Spectral")
g4
Un avantage immédiat du PoS, est qu’on peut se concentrer sur certaines parties du discours. Les adjectifs par exemple sont sans doute le principal moyen linguistique pour les consommateurs d’exprimer leurs sentiments et de traduire leur expérience. L’usage de l’hyperbolarisation et l’emphase.
On obtient immédiatement une vue assez claire sur les adjectifs épithètes ou non. les petit et bon semblent se rapporter au petit déjeuner, la nourriture est essentielle. Ensuite viennent les superlatifs.
Les verbes où domine le verbe “avoir” suivi par celui de “pouvoir” et de “faire” . Voilà qui met le discours à la longueur d’onde de la possession, la capacité de disposer des choses. Avoir pour pouvoir faire.
“Aller”, “passer”, “séjourner” marquent le mouvement nécessaire du voyageur, mais viennent en second rang. Le regard vient en troisième position (pouvions nous penser qu’il ait un meilleur rang ?), les autres termes, marginaux, concernent l’idée de la mémoration (l’extension mémorielle du regard ?).
#on se concentre sur les adjectifs et les verbes
Vocab_adj<-subset(Vocab, upos=="ADJ")
Table <- with(Vocab_adj, table(lemma))
cat("\ncounts:\n")
##
## counts:
ling<-as.data.frame(Table)
ling<-subset(ling,Freq>1000)
g20<-ggplot(ling,aes(x=reorder(lemma,Freq),y=Freq))+geom_point()+coord_flip()+theme_minimal()+theme(text = element_text(size=9))
Vocab_adj<-subset(Vocab, upos=="VERB")
Table <- with(Vocab_adj, table(lemma))
cat("\ncounts:\n")
##
## counts:
ling<-as.data.frame(Table)
ling<-subset(ling,Freq>1000)
g21<-ggplot(ling,aes(x=reorder(lemma,Freq),y=Freq))+geom_point()+coord_flip()+theme_minimal()+theme(text = element_text(size=10))
grid.arrange(g20,g21,ncol=2) #utilise gridextra
Les manières de mesurer le sentiment se partgent entre deux familles La première que nous n’explorons pas dans ce carnet, consiste à etiquetter manuellement un échantillon d’entrainement (une note de sentiment, de préfèrence avec plusieurs codeurs), puis à développer un modèle prédictif ( du lasso, des RF ou du SVM, tout doit être tenté! et que le meilleur gagne). Si les résultats sont satisfaisants on généralise à la totalité du corpus. C’est un processus qui peut être lourd quand le set de training doit être important. Amazon Mechanical Turk est une ressource importante pour cette tâche. Ce sont des pratiques qui participent à l’organisation du digital labor (ref casilli)
L’autre manière de calculer le sentiment est compositionnelle. Elles s’appuie sur des dictionnaires de mots qui ont été évalué auparavant et testés dans différent univers. Chaque mot est doté d’une valence ( -1;0,+1) et on agrège en standardisation ldes valences des mots d’une phrase, d’un paragraphe, d’un texte.
Dans l’exemple on s’appuit sur la méthode NRC (Mohammad and Turney (2013) ) qui en plus de la valence permet d’attribuer à chaque unité textuelle, une ou plusieurs émotions dans une palette de huit inspirée des émotions de base de Plutchik (1982) . On retrouve ainsi une variable d’importance dans le champs de l’analyse du comportements des consommateurs (voir par exemple xxx ou encore xxx)
Cet indicateur est fourni dans le package syuzhet
avec les méthode bing et Affin (qui cependant n’ont pas de dictionnaire français). Un inventaire des ressources disponibles ( en français et dans les différentes langues) serait particulièrement utile. Signalons celles de stanfordNLP, mais aussi…
La mise en oeuvre est excessivement simple :
method <- "nrc"
lang <- "french"
phrase<-as.character(dupBase4$text)
#extraction
my_text<- get_sentiment(phrase, method=method, language=lang)
my_text[1:5]
## [1] 1 8 4 5 3
Voici la distribution de la valence selon les contenus et son évolution dans le temps.
Mais on peut aller plus loin, ce document en donne une très belle idée
#on complète la base
sent<-as.data.frame(my_text)
sent$sentiment<-as.numeric(sent$my_text)
dupBase5<-cbind(dupBase4,sent)
ag<-subset(dupBase5, select=c(sentiment, year))
g30<- ggplot(ag, aes(x=sentiment))+geom_density()
ag<-aggregate(sentiment~year,data=ag, FUN=mean)
g31<- ggplot(ag, aes(x=year, y=sentiment))+geom_point()
grid.arrange(g30,g31,ncol=2) #utilise gridextra
Et voici la distribution des émotions par ordre de fréquence. Les émotions positives dominent, ce qui est peu étonnant. Du côté des émotions c’est la confiance et l’anticipation qui l’emportent, la joie et la surprise sont moins fréquentes.
emotions <- get_nrc_sentiment(phrase)
emo_bar = colSums(emotions)
emo_sum = data.frame(count=emo_bar, emotion=names(emo_bar))
emo_sum$emotion = factor(emo_sum$emotion, levels=emo_sum$emotion[order(emo_sum$count, decreasing = FALSE)])
ggplot(emo_sum, aes(x=emotion, y=count,fill=emotion))+geom_bar(stat="identity")
comp<-cbind(dupBase5,emotions)
comp <- subset(comp, select=c(anger,anticipation,Archipel,ARI,Avis,C,
Coleman,CTTR,D,date,disgust,fear,hotel,id,Ile,joy,K,lgeV0,lgV0,Maas,
meanSentenceLength,meanWordSyllables,my_text,nbcar,NbChambres,negative,
NombreEtoiles,NombreRestaurants,pos,positive,Prix,Prix_classe,
PrixMoyenChambreStandard,R,Rating,S,sadness,sentiment,sum,surprise,text,
trust,TTR,U,uADJ,uADV,uELSE,uNOUN,uVERB,Vm,x,y,year,year2))
save(comp,file="comp.Rda")
Et bien sur du lda dont l’article de Canini, Shi, and Griffiths (2009) ou de Blei, Ng, and Jordan (2003). On en trouvera une présentation en français à la fois simple et détaillée sur le plan mathématique
le principe est finalement simple : chaque mot est susceptible d’appartenir à K concepts de même que chaque document. La probabilité est multivariée et on comprend que ce soit la loi de dirichlet qui modèlise avec la plus grande pertinence cette distribution multinomiale et les probabilités qu’un terme ou un document soit associé au topic. Le nombre de modalités est très élevé dans notre cas : 12000 documents et 24000 termes.
Un premier aperçu est donné par la liste des 15 premiers termes. On prend la précaution d’utiliser les tokens, déjà filtrés (stopword et autres)
En tenant compte d’essais antérieurs un modèle à 6 topic est optimal (voir ci-dessous)
#model
library(tidytext)
df_lda <-Vocab %>% filter(upos=="ADJ")
df_lda<-subset(df_lda,select=c(id,lemma))
df_lda$value<-1
df_lda<-cast_dfm(df_lda, id, lemma,value)
dtm <- convert(df_lda, to = "topicmodels")
lda <- LDA(dtm, k = 12)
terms(lda, 15)
## Topic 1 Topic 2 Topic 3 Topic 4
## [1,] "magnifique" "petit" "agréable" "beau"
## [2,] "petit" "grand" "grand" "bon"
## [3,] "parfait" "beau" "excellent" "magnifique"
## [4,] "spacieux" "spacieux" "incroyable" "incroyable"
## [5,] "bon" "propre" "autre" "parfait"
## [6,] "super" "confortable" "propre" "autre"
## [7,] "propre" "super" "meilleur" "cher"
## [8,] "confortable" "meilleur" "gratuit" "premier"
## [9,] "sympa" "seul" "cher" "super"
## [10,] "charmant" "magnifique" "beau" "agréable"
## [11,] "seul" "cher" "sympathique" "grand"
## [12,] "beau" "personnel" "super" "meilleur"
## [13,] "exceptionnel" "parfait" "petit" "serviable"
## [14,] "délicieux" "excellent" "délicieux" "privé"
## [15,] "chaleureux" "incroyable" "correct" "seul"
## Topic 5 Topic 6 Topic 7 Topic 8
## [1,] "petit" "bon" "beau" "bon"
## [2,] "grand" "petit" "agréable" "excellent"
## [3,] "bon" "agréable" "propre" "beau"
## [4,] "magnifique" "excellent" "confortable" "spacieux"
## [5,] "parfait" "propre" "incroyable" "magnifique"
## [6,] "autre" "meilleur" "bon" "propre"
## [7,] "agréable" "merveilleux" "serviable" "confortable"
## [8,] "superbe" "super" "super" "super"
## [9,] "sympathique" "spacieux" "sympathique" "seul"
## [10,] "meilleur" "cher" "grand" "chaleureux"
## [11,] "confortable" "beau" "chaleureux" "merveilleux"
## [12,] "seul" "premier" "fantastique" "autre"
## [13,] "propre" "seul" "merveilleux" "idéal"
## [14,] "serviable" "sympa" "parfait" "grand"
## [15,] "cher" "délicieux" "cher" "personnel"
## Topic 9 Topic 10 Topic 11 Topic 12
## [1,] "bon" "agréable" "magnifique" "petit"
## [2,] "magnifique" "autre" "agréable" "beau"
## [3,] "excellent" "meilleur" "exceptionnel" "excellent"
## [4,] "superbe" "propre" "propre" "magnifique"
## [5,] "petit" "personnel" "parfait" "agréable"
## [6,] "meilleur" "gratuit" "privé" "autre"
## [7,] "merveilleux" "excellent" "superbe" "sympa"
## [8,] "sympa" "beau" "personnel" "premier"
## [9,] "seul" "serviable" "gratuit" "chaleureux"
## [10,] "serviable" "sympathique" "excellent" "joli"
## [11,] "incroyable" "spacieux" "gentil" "sympathique"
## [12,] "autre" "grand" "fantastique" "superbe"
## [13,] "français" "seul" "correct" "cher"
## [14,] "polynésien" "fantastique" "immense" "extraordinaire"
## [15,] "vrai" "délicieux" "génial" "principal"
A ce stade cetains topic se dessinnent * topic 1 : Superlatif * topic 2 : confortable sensuel * topic 3 : plongée plage * topic 4 : magnifique * topic 5 : arrivée positif * topic 6 : propre * topic 7 : bora bora * topic 8 : * topic 9 : nouriture * topic 10 : experience
le code de la représentation graphique vient d’ici
(attention un pb non resolu de lecture de fichier peut apparaitre meme si le code est bon - erreur connue et non résolue)
library(tidytext)
ap_topics <- tidy(lda, matrix=c("beta"))
ap_top_terms <- ap_topics %>%
group_by(topic) %>%
top_n(20, beta) %>%
ungroup() %>%
arrange(topic, -beta)
ap_top_terms %>%
mutate(term = reorder(term, beta)) %>%
ggplot(aes(term, beta, fill = factor(topic))) +
geom_col(show.legend = FALSE) +
facet_wrap(~ topic, scales = "free") +
coord_flip()
Naturellement chaque texte est lui même scoré, c’est la matrice gamma qui donne la proportion de texte d’un document qui se réfère à un sujet particulier.
Examinons donc les thèmes selon les iles, en calculant la proportion moyennes d’appartenir aux k topics par iles, on devrait obtenir une représentation de ce qui s’y dit.
#on attribue le topic au document
#docvars(df_lda, 'topic') <- topics(lda) (bud individu perdus...)
ap_doc <- tidy(lda, matrix="gamma")
ap_doc$topic <-as.factor(ap_doc$topic)
ap_doc$Topic1<-0
ap_doc$Topic2<-0
ap_doc$Topic3<-0
ap_doc$Topic4<-0
ap_doc$Topic5<-0
ap_doc$Topic6<-0
ap_doc$Topic1[ap_doc$topic==1]<-ap_doc$gamma
ap_doc$Topic2[ap_doc$topic==2]<-ap_doc$gamma
ap_doc$Topic3[ap_doc$topic==3]<-ap_doc$gamma
ap_doc$Topic4[ap_doc$topic==4]<-ap_doc$gamma
ap_doc$Topic5[ap_doc$topic==5]<-ap_doc$gamma
ap_doc$Topic6[ap_doc$topic==6]<-ap_doc$gamma
ap_doc$document<-as.factor(ap_doc$document)
profil<-aggregate(cbind(Topic1,Topic2,Topic3,Topic4,Topic5)~ document,ap_doc,FUN = "sum")
lex$document<-as.factor(lex$document)
topic_text<-merge(lex,profil,by.x="document",by.y="document", all.x = TRUE,all.y=FALSE)
#Ag<- aggregate(cbind(Topic1,Topic2,Topic3,Topic4,Topic5) ~ year, data=topic_text, FUN=sum)
#Ag<-melt(Ag) # avec library(reshape2)
#g1<-ggplot(Ag,aes(x=year,y=value,group= variable))+geom_line(stat="identity",aes(col=variable),size=1)
#g1+scale_color_brewer(palette = "Spectral")
L’inconvénient de la méthode LDA est que le nombre de topics latents est un paramètre fixé à priori et sans indication préalable. de nombreux essais peuvent être nécessaires.
Il est cependant possible par une méthode de grille (on évalue successivement des solutions à nombres croissants de topics) d’identifier un nombre optimal. Dans cette esprit Une méthode disponible sur r est proposée par la librarie ldatuning qui propose 4 métriques d’évaluation pour différentes méthodes d’estimation (dans notre cas c’est celle de Gibbs qui est testée).
Attention la procédure peut être gourmande en temps, dans notre cas (et avec notre équipement - ok mais pas top) c’est une affaire de dizaines de minutes de calcul, faites attention ! Il y aurait un optimum autour de 25 avec l’indicateur de Deveaud, mais à partir de k= 15 il semble que les améliorations soient faibles.
library(ldatuning)
#attention très long ( quelques heures)
result <- FindTopicsNumber( dtm,
topics = seq(from = 2, to = 10, by = 1),
metrics = c("Griffiths2004", "CaoJuan2009", "Arun2010", "Deveaud2014"),
method = "Gibbs",
control = list(seed = 77),
mc.cores = 2L,
verbose = TRUE
)
## fit models... done.
## calculate metrics:
## Griffiths2004... done.
## CaoJuan2009... done.
## Arun2010... done.
## Deveaud2014... done.
FindTopicsNumber_plot(result)
On présente les résultats en deux temps. d’abord des comparaison entre les niveaux statuts d’hôtels sur les critères de compétences langagières, ensuite les différences sur les contenus exprimés.
Les critères de comparaison sont le prix et le nombre d’étoiles qui cadrent le statut de l’hôtel. On fera un contrôle selon le temps sur une base annuelle et l’ile ou l’archipel.
On examinera avant le f de cohen ( ref @), plutôt que les p values.
La comparaison systématique de ces indicateurs pour différents groupes d’hôtels signalés par leur prix et par leur nombre d’étoiles est engagée. Un contrôle par le temps est effectué.
Distinguer des catégories d’hotels par leurs étoiles, leurs notes ou leur prix, c’est reconnaitre une grandeur donc ces trois variables particpent à ,la construction du vecteur qui distinguent les moins dotés , des plus dotés, de cette constante de la distribution des ressources matérielles et culturelles qui caractérisent les sociétés. ( bourdieu) Différentes classes s’adressent à différentes classes qui diffèrent par le budgets ( lunes de miel à 20 000 euos) mais aussi fort probablement à des différences de capital culturels, qui se manifestent autant en termes de diplôme ( ce que nous n’obervons) pas que de compétences langagières acquise autanbt par l’éduccation que par l’éthos. Les classes les plus aisées se distinguent aussi par leur maîtrise de la langue légitimes. Elle a maitrisé ses classiques, elle lit houellebecq. A l’autre extrémité il y a une langue qui maitrise mal les règles grammaticale, se contentente d’etre communicable avec bruit, se fabrique dans l’oralité, et considère l’écriture cmme une steno informelle.
commençons par la longueur des avis en nombre de caractères.
Le test d’analyse de variance dont la structure générale est répétée pour tous les indicateurs (main effects + interaction prix x taille + year+ archipel ) donne les résultats suivants :
model <- lm(nbcar ~ Prix_classe+NbChambres+year,
data = comp,
contrasts = list(Prix_classe = "contr.sum", Archipel = "contr.sum"))
library(sjstats) # les f de cohen etc
df<-anova_stats(car::Anova(model, type = 3))
keeps <- c("term", "sumsq","meansq","df","statistic","p.value","etasq","cohens.f","power")
kable(df[keeps], digits = 3, booktabs = TRUE, caption = 'Analyse de variance, taille d effet et puissance du test')%>%
kable_styling(bootstrap_options = "striped", full_width = F,font_size = 10)
term | sumsq | meansq | df | statistic | p.value | etasq | cohens.f | power |
---|---|---|---|---|---|---|---|---|
(Intercept) | 291420794 | 291420794 | 1 | 565.878 | 0 | 0.068 | 0.279 | 1 |
Prix_classe | 18282813 | 6094271 | 3 | 11.834 | 0 | 0.004 | 0.070 | 1 |
NbChambres | 189185846 | 63061949 | 3 | 122.453 | 0 | 0.044 | 0.225 | 1 |
year | 83074994 | 11867856 | 7 | 23.045 | 0 | 0.019 | 0.149 | 1 |
Residuals | 3733670422 | 514989 | 7250 | NA | NA | NA | NA | NA |
write.csv(comp,'comp.csv')
Une première analyse peut être menée sur la taille des avis. On observe une relation curvilinaire. les hotels de luxe et les plus modestes ont les commentateurs plus prolixes. Les hotels intermédiaires semblent n’encourager que des avis courts. Sont-ils moins engageants si on considère que la longueur en nombre de caractères mesure aussi l’effort qu’a produit le commentateur.
g03<- ggplot(comp,aes(x=Prix))+geom_histogram(binwidth=500)+xlim(0,50000)+geom_histogram(fill="grey") +theme_minimal()+ labs(title = "Distribution des prix", x="Prix", y="nombre d'annonces")
comp[1,]
## anger anticipation Archipel ARI Avis
## 1 0 0 Iles Sous-le-Vent (Raromata'i) 11.30113 110
## C Coleman CTTR D date disgust fear
## 1 0.9387341 36.37 5.285714 0.04923206 juillet 2018 0 0
## hotel id Ile joy K
## 1 Family_Hotel_Fare_Vai_Nui-Uturoa_Raiatea doc1 Raiatea 0 589.3378
## lgeV0 lgV0 Maas meanSentenceLength meanWordSyllables my_text
## 1 12.4885 5.423685 0.175408 16.66667 1.68 1
## nbcar NbChambres negative NombreEtoiles NombreRestaurants
## 1 315 1 moins de 10 chambres 0 3 1
## pos positive Prix Prix_classe PrixMoyenChambreStandard R Rating
## 1 8 1 74354 4 Luxuous 27532 XPF 7.475129 3
## S sadness sentiment sum surprise
## 1 0.9082062 0 1 58 0
## text
## 1 quietude et bonne table Tres bien accueillis par Jean Jacques et Chantal qui est une excellente cuisinière.l'endroit est d'ailleurs réputé pour la qualité de sa restauration. Jean Jacques, est venu chercher les garçons pour regarder avec eux les matchs de la coupe du monde dans autre bugalows disposant d'...Plus
## trust TTR U uADJ uADV uELSE uNOUN
## 1 0 0.755102 32.50135 0.06896552 0.03448276 0.6206897 0.1724138
## uVERB Vm x y year year2
## 1 0.1034483 0.2131203 <NA> <NA> 2018 2018
comp$Prix_classe<-as.factor(comp$Prix_classe)
d04<-aggregate(nbcar~Prix_classe,data=comp,FUN=mean)
g04<-ggplot(d04,aes(x=Prix_classe,nbcar),y=nbcar)+geom_point(size=2)+geom_segment( aes(x=Prix_classe, xend=Prix_classe, y=400, yend=nbcar))+theme_minimal()+ labs(title = "Taille moyenne des avis par classes de prix", x="Iles", y="nombre de caractères")+ylim(400,700)+coord_flip()
g04
comp$NbChambres<-as.factor(comp$NbChambres)
d05<-aggregate(nbcar~NbChambres,data=comp,FUN=mean)
g05<-ggplot(d05,aes(x=NbChambres,nbcar),y=nbcar)+geom_point(size=2)+geom_segment( aes(x=NbChambres, xend=NbChambres, y=300, yend=nbcar))+theme_minimal()+ labs(title = "Taille moyenne des avis par classes de prix", x="Iles", y="nombre de caractères")+ylim(300,700)+coord_flip()
g05
grid.arrange(g03,g04,g05,ncol=3) #utilise gridextra
On teste l’effet sur les indicaturs de lisibilité des mêmes variables et de la même manière.
le premier test porte sur le nombre moyen de syllabes.
model <- lm(meanWordSyllables ~ Prix_classe+NbChambres+year+Ile,
data = comp,
contrasts = list(Prix_classe = "contr.sum", NbChambres= "contr.sum",year= "contr.sum",Archipel = "contr.sum"))
#library(sjstats) # les f de cohen etc
df<-anova_stats(car::Anova(model, type = 3))
keeps <- c("term", "sumsq","meansq","df","statistic","p.value","etasq","cohens.f","power")
kable(df[keeps], digits = 3, booktabs = TRUE, caption = 'Nombre de syllabes par mot - Anova, taille effet et puissance du test')%>%
kable_styling(bootstrap_options = "striped", full_width = F,font_size = 10)
term | sumsq | meansq | df | statistic | p.value | etasq | cohens.f | power |
---|---|---|---|---|---|---|---|---|
(Intercept) | 967.003 | 967.003 | 1 | 50602.935 | 0.000 | 0.873 | 2.650 | 1.000 |
Prix_classe | 0.032 | 0.011 | 3 | 0.565 | 0.638 | 0.000 | 0.015 | 0.168 |
NbChambres | 0.060 | 0.020 | 3 | 1.045 | 0.371 | 0.000 | 0.021 | 0.286 |
year | 1.307 | 0.187 | 7 | 9.767 | 0.000 | 0.001 | 0.097 | 1.000 |
Ile | 0.994 | 0.058 | 17 | 3.061 | 0.000 | 0.001 | 0.085 | 0.999 |
Residuals | 137.666 | 0.019 | 7204 | NA | NA | NA | NA | NA |
deuxième test sur la longueur moyenne des phrases
model <- lm(meanSentenceLength ~ Prix_classe+NbChambres+year,
data = comp,
contrasts = list(Prix_classe = "contr.sum", NbChambres= "contr.sum",year= "contr.sum",Archipel = "contr.sum"))
#library(sjstats) # les f de cohen etc
df<-anova_stats(car::Anova(model, type = 3))
keeps <- c("term", "sumsq","meansq","df","statistic","p.value","etasq","cohens.f","power")
kable(df[keeps], digits = 3, booktabs = TRUE, caption = 'Longueur de phrase - Anova, taille effet et puissance du test')%>%
kable_styling(bootstrap_options = "striped", full_width = F,font_size = 10)
term | sumsq | meansq | df | statistic | p.value | etasq | cohens.f | power |
---|---|---|---|---|---|---|---|---|
(Intercept) | 732434.095 | 732434.095 | 1 | 17529.449 | 0.000 | 0.706 | 1.555 | 1.000 |
Prix_classe | 121.664 | 40.555 | 3 | 0.971 | 0.405 | 0.000 | 0.020 | 0.267 |
NbChambres | 356.983 | 118.994 | 3 | 2.848 | 0.036 | 0.000 | 0.034 | 0.686 |
year | 1766.417 | 252.345 | 7 | 6.039 | 0.000 | 0.002 | 0.076 | 1.000 |
Residuals | 302927.225 | 41.783 | 7250 | NA | NA | NA | NA | NA |
troisième test sur le test ARI
model <- lm(Maas ~ Prix_classe+NbChambres+year,
data = comp,
contrasts = list(Prix_classe = "contr.sum", NbChambres= "contr.sum",year= "contr.sum",Archipel = "contr.sum"))
#library(sjstats) # les f de cohen etc
df<-anova_stats(car::Anova(model, type = 3))
keeps <- c("term", "sumsq","meansq","df","statistic","p.value","etasq","cohens.f","power")
kable(df[keeps], digits = 3, booktabs = TRUE, caption = 'ARI - Anova, taille effet et puissance du test')%>%
kable_styling(bootstrap_options = "striped", full_width = F,font_size = 10)
term | sumsq | meansq | df | statistic | p.value | etasq | cohens.f | power |
---|---|---|---|---|---|---|---|---|
(Intercept) | 98.652 | 98.652 | 1 | 156620.781 | 0.000 | 0.955 | 4.648 | 1.000 |
Prix_classe | 0.002 | 0.001 | 3 | 0.795 | 0.497 | 0.000 | 0.018 | 0.223 |
NbChambres | 0.007 | 0.002 | 3 | 3.692 | 0.011 | 0.000 | 0.039 | 0.807 |
year | 0.046 | 0.007 | 7 | 10.525 | 0.000 | 0.000 | 0.101 | 1.000 |
Residuals | 4.567 | 0.001 | 7250 | NA | NA | NA | NA | NA |
Une représentation graphique
Ag<- aggregate(cbind(meanWordSyllables,meanSentenceLength,ARI) ~ Prix_classe+year, data=comp, FUN=mean)
Ag <- melt(Ag, id=c("Prix_classe","year"))
g7<-ggplot(Ag,aes(x=year,y=value,color =Prix_classe))+geom_line(size=1.2, aes(group=Prix_classe))+theme_minimal()+ labs(title = "Taille moyenne des avis par classes de prix", x="Niveaux de prix", y="Indicateurs de lisibilité") +facet_grid(variable~.,scales ="free")
g7
Pour la variété lexicale on se concentre sur le C de herdall.
Ag<- aggregate(cbind(D,Maas) ~ Prix_classe+year, data=comp, FUN=mean)
Ag <- melt(Ag, id=c("Prix_classe","year"))
g7<-ggplot(Ag,aes(x=year,y=value,color =Prix_classe))+geom_line(size=1.2, aes(group=Prix_classe))+theme_minimal()+ labs(title = "Taille moyenne des avis par classes de prix", x="Niveaux de prix", y="Indicateurs de lisibilité") +facet_grid(variable~.,scales ="free")
g7
On teste d’abord l’effet géographique, les archipels, car il représentent des paysages, des environnements mais aussi des équipements variés. (rem : il faudra les décrire en introduction et puis insérer une carte) voir aussi http://www.understandingdata.net/2017/05/11/anova-tables-in-r/#APAtable pour analyse avec contrastes.
model <- lm(sentiment ~ Prix_classe+NbChambres+year,
data = comp,
contrasts = list(Prix_classe = "contr.sum", Archipel = "contr.sum"))
library(sjstats) # les f de cohen etc
df<-anova_stats(car::Anova(model, type = 3))
keeps <- c("term", "sumsq","meansq","df","statistic","etasq","cohens.f","power")
kable(df[keeps], digits = 3, booktabs = TRUE, caption = 'Analyse de variance, taille d effet et puissance du test')%>%
kable_styling(bootstrap_options = "striped", full_width = F,font_size = 10)
term | sumsq | meansq | df | statistic | etasq | cohens.f | power |
---|---|---|---|---|---|---|---|
(Intercept) | 11383.160 | 11383.160 | 1 | 481.015 | 0.060 | 0.258 | 1.000 |
Prix_classe | 634.420 | 211.473 | 3 | 8.936 | 0.003 | 0.061 | 0.996 |
NbChambres | 3882.611 | 1294.204 | 3 | 54.689 | 0.021 | 0.150 | 1.000 |
year | 1735.163 | 247.880 | 7 | 10.475 | 0.009 | 0.101 | 1.000 |
Residuals | 171570.329 | 23.665 | 7250 | NA | NA | NA | NA |
Ag<- aggregate(cbind(sentiment) ~ Prix_classe+year, data=comp, FUN=mean)
Ag <- melt(Ag, id=c("Prix_classe","year"))
g7<-ggplot(Ag,aes(x=year,y=value,color =Prix_classe))+geom_line(size=1.2, aes(group=Prix_classe))+theme_minimal()+ labs(title = "Taille moyenne des avis par classes de prix", x="Niveaux de prix", y="Indicateurs de lisibilité")
g7
les effets sont moins marqués. c’est l’hôtel qui est source de déception, les sentiments négatifs sont aussi associés à l’environnement. C’est une hypothèse à tester.
Pour mieux visaliser les différences
Ag<- aggregate(cbind(positive,negative) ~ Prix_classe, data=comp, FUN=mean)
Ag$negative<-(-1*Ag$negative)
Ag<-melt(Ag) # avec library(reshape2)
g31<-ggplot(Ag,aes(x=Prix_classe,y=value,group= variable))+geom_bar(stat="identity",aes(fill=variable),size=2) +coord_flip()
grid.arrange(g30,g31) #utilise gridextra
Ag<- aggregate(cbind(positive,negative) ~ year+Prix_classe, data=comp, FUN=mean)
Ag <- melt(Ag, id=c("Prix_classe","year"))
g32<-ggplot(Ag,aes(x=year,y=value,color =variable))+geom_line(size=1.2, aes(group=variable))+theme_minimal()+ labs(title = "Taille moyenne des avis par classes de prix", x="Niveaux de prix", y="Sentiment négatif") +facet_grid(Prix_classe~.,scales ="free")+scale_color_manual(values=wes_palette("IsleofDogs1", n = 2))
g32
Intéressons nous maintenant aux émotions.
pour le test éxaminons d’abord les relations entre les émotions en visualisant leurs corrélations avec corplot, Le résulat
X<-subset(comp,select=cbind(sadness,joy,trust,anger,anticipation,disgust,fear,surprise))
M <- cor(X)
corrplot(M, order = "hclust", addrect = 2, col = heat.colors(100))
Une analyse typologique simple complète avec clarté. Les émotions sont complémentaires, se renforcent s’associent.
plot(hclust(dist(M)))
comp$sum<-(comp$sadness+comp$joy+comp$trust+comp$anger+comp$anticipation+comp$disgust+comp$fear+comp$surprise)
comp$disgust<-comp$disgust/comp$sum
comp$anger<-comp$anger/comp$sum
comp$fear<-comp$fear/comp$sum
comp$sadness<-comp$sadness/comp$sum
comp$surprise<-comp$surprise/comp$sum
comp$anticipation<-comp$anticipation/comp$sum
comp$trust<-comp$trust/comp$sum
comp$joy<-comp$joy/comp$sum
Ag<- aggregate(cbind(sadness,joy,trust,anger,anticipation,disgust,fear,surprise) ~ Prix_classe, data=comp, FUN=mean)
Ag<-subset(Ag,select=c(Prix_classe,sadness,joy,trust,anger,anticipation,disgust,fear,surprise))
Ag<-melt(Ag) # avec library(reshape2)
Ag$variable <- with(Ag, factor(variable, levels=c('joy','trust',
'anticipation','surprise','sadness','fear','anger','disgust'),
ordered=TRUE))
g1<-ggplot(Ag,aes(x=Prix_classe,y=value,group= variable))+geom_line(stat="identity",aes(col=variable),size=2)
g1+scale_color_brewer(palette = "Spectral")
#un peu plus de codage pour relier à la plaette des emotions
Ag<- aggregate(cbind(sadness,joy,trust,anger,anticipation,disgust,fear,surprise) ~ year, data=comp, FUN=mean)
Ag<-melt(Ag)
g4<-ggplot(Ag,aes(x=year,y=value,group= variable))+geom_bar(stat="identity",aes(fill=variable),size=2) +coord_flip()+scale_fill_brewer(palette = "Spectral")
g4
test du nombre de chambre prix
On conduit l’analyse lexicale, car s’appuyant sur le lexique, et thématique, car visant à identifier des sujets d’expression avec la méthode LDA, en trois étapes :
Les deux wordclouds qui suivent sont respectivement construits sur les tokens, non lemmatisés puis lemmatisés. Un filtre est construit pour éliminer les tokens cités dans plus de 8%, on retient ceux dont la fréquence est supérieures à 30.
#wordcloud et fréquence
set.seed(100) #pour rehouer le hasard de la même mani-re et etproduire les resultats
#un filtre sur les frequence relatives
dfm<-dfm(toks, tolower = TRUE,stem=FALSE) %>%
dfm_trim(min_termfreq = 0.95, termfreq_type = "quantile", max_docfreq = 0.10, docfreq_type = "prop")
#le plot
textplot_wordcloud(dfm,min_count = 50, color = c('pink', 'red', 'orange','purple', 'blue'))
# avec stemming
#set.seed(100) #pour rehouer le hasard de la même mani-re et etproduire les resultats
#dfm<-dfm(toks, tolower = TRUE,stem=TRUE) %>%
# dfm(remove = stopwords('fr'), remove_punct = TRUE) %>%
# dfm_trim(min_termfreq = 0.95, termfreq_type = "quantile", max_docfreq = 0.10, docfreq_type = "prop")
#textplot_wordcloud(dfm,min_count = 50, color = c('pink', 'red', 'orange','purple', 'blue'))
Sur les adjectifs et les verbes
on obtient ceci
Vocab_adj<-subset(Vocab, upos=="ADJ")
Table <- with(Vocab_adj, table(lemma))
cat("\ncounts:\n")
##
## counts:
ling<-as.data.frame(Table)
ling<-subset(ling,Freq>30)
wordcloud(words = ling$lemma, freq = ling$Freq, min.freq = 1,
max.words=200, random.order=FALSE, rot.per=0.35,
colors=brewer.pal(8, "Dark2"))
Vocab_verb<-subset(Vocab, upos=="VERB")
Table <- with(Vocab_verb, table(lemma))
cat("\ncounts:\n")
##
## counts:
ling<-as.data.frame(Table)
ling<-subset(ling,Freq>30)
wordcloud(words = ling$lemma, freq = ling$Freq, min.freq = 1,
max.words=200, random.order=FALSE, rot.per=0.35,
colors=brewer.pal(8, "Dark2"))
Cette représentation globalisante peut être fractionnée selon les textes. En segmentant en fonction de la classe de prix, on fait emerger un vocabulaire plus différenciés : à moin de 60 euros c’est xxx, ça devient xxx dans la tranche 60-100, plus familial, en gardant le charme pour les 100-150 euros, et pour les prix les plus élevés devient luxueux et magnifiques.
dfmcomp <- dfm(Corpus, groups = "Prix_classe")
textplot_wordcloud(dfmcomp, comparison = TRUE, max_words = 200,labelsize = 0.9)
Si les nuages de points sont plaisants, de simples diagrammes de fréquence peuvent être utiles pour distinguer les catégories, quand elles sont nombreuses.
Dans l’exemple suivante on représente pour un élément de lexique, leur fréquence pour chacun des archipels de la polynésie.
freq_dfm <- textstat_frequency(dfm, groups = "Archipel")
term="plongée"
freq_room <- subset(freq_dfm, freq_dfm$feature %in% "plongée") #attention à la graphie si stemming
ggplot(freq_room, aes(x = reorder(group,frequency), y = frequency)) +
geom_point(size=3) +
scale_y_continuous(limits = c(0, 1000), breaks = c(seq(0, 1000, 100))) +
xlab(NULL) +
ylab("Frequency") +
theme(axis.text.x = element_text(angle = 90, hjust = 1, size=),axis.text.y = element_text(size=9))+
coord_flip()+labs(title=paste0(term))
L’analyse sémantique latente est en fait un modèle SVD ( Singular Vector Decomposition) familiers à ceux qui connaissent l’analyse en composante principales. La différence est que dans le cas de l’ACP la décomposition en vecteurs singuliers se fait sur la matrice de variance covariance (si X est le tableau de donnée S=XXT), alors que le SVD traite le tableau d’occurences des termes dans les textes.( pour aller plus loin voir par exemple).
L’objectif est de décomposer une matrice tdm (term document matrix) en trois éléments comme l’illustre le diagramme suivant. voir aussi LSAfun
On en extrait les vecteurs documents et features qui sont désormais représenté dans un espace à 10 dimensions.
#analyse semantique latente
mylsa <- textmodel_lsa(dfm)
proxD<-mylsa$docs[, 1:10]
head(proxD,4)
## [,1] [,2] [,3] [,4] [,5]
## 1 -0.002483552 0.0006256621 -0.0012489244 0.006806246 -0.002192051
## 2 -0.002769327 0.0002027760 -0.0013861542 0.010646843 -0.003240699
## 7 -0.002368431 -0.0001455822 -0.0009542148 0.004053241 -0.005565489
## 9 -0.001456966 -0.0014922424 -0.0006014717 0.006909055 -0.004461717
## [,6] [,7] [,8] [,9] [,10]
## 1 0.0009567438 -0.002587654 -0.002097137 -0.002033453 0.0029391094
## 2 0.0036614777 -0.003527407 0.002523933 -0.001202971 0.0068644574
## 7 0.0031062643 -0.001979527 -0.002311580 -0.004344956 0.0020710985
## 9 0.0034936732 -0.001724977 -0.003026531 -0.005235428 0.0005446607
proxF<-mylsa$features[, 1:10]
head(proxF,5)
## [,1] [,2] [,3] [,4] [,5]
## tabl -0.050887846 0.019465242 -0.0051713766 0.041813204 0.088723184
## tres -0.005008014 0.024595617 -0.0286596289 0.086724625 -0.073239921
## accueilli -0.043906123 -0.008666002 -0.0040749871 0.063027905 0.052187197
## jean -0.003279426 -0.003764574 -0.0005145214 0.009380954 -0.005621227
## excellent -0.017263676 -0.005402803 -0.0083750151 0.056723487 -0.026744900
## [,6] [,7] [,8] [,9]
## tabl -0.011197126 0.003120893 0.1072693325 -0.026173049
## tres 0.014219849 -0.002137370 0.0048336878 -0.062570128
## accueilli -0.010006300 -0.028612193 -0.0848870199 0.023528603
## jean 0.001340671 -0.011098151 -0.0008441276 -0.003192395
## excellent 0.002065853 -0.008869537 -0.0195502516 -0.014599709
## [,10]
## tabl -0.041377952
## tres 0.036510003
## accueilli -0.025906699
## jean 0.002979571
## excellent 0.022335857
On utilise ces résultats pour faire une analyse des proximités et représenter les similarités entre les termes.Plutôt que d’utiliser les classiques “Multidimensional Scaling”" (MDS) on opte, car le nombre d’objets textes est élevé, pour une méthode t-SNE dont la remarquable propriété de “gondoler” l’espace en fonction de la distribution des points : quand localement la densité des points est élevée ( c’est le sens de t-Distributed Stochastic Neighbor Embedding (t-SNE) les distances sont majorées, alors que pour des paquets éloignées elles seront minorées. (c’est en fait une théorie générale de la relativité qui s’oppose au modèle newtownien).
Elle permet de représenter de grands ensembles d’objets (nous en avons 12000 document individus et 1200 termes) en contrôlant le paramètre clé, celui de la perplexité (une sorte de cintrage ou de torsion de l’espace qui donne un poids plus important quand la densité locale des points est importante et dilate l’espace).
Ici on se concentre sur les features
https://link.springer.com/article/10.3758/s13428-014-0529-0
prox<-mylsa$features[, 1:10]
terms<-as.data.frame(prox)
#rtsne
tsne_out <- Rtsne(terms, dims = 2, initial_dims = 50,
perplexity = 20, theta = 0.5, check_duplicates = FALSE,
pca = TRUE, max_iter = 300)
#plot(tsne_out$Y) #pour tester rapidement les effets de la perplexité
x<-tsne_out$Y #extraction des coordonnee
#construction du tableau termes - coordonnée
terms$term<-row.names(prox)
plot<-cbind(x,terms)
plot$F1<-plot[,1]
plot$F2<-plot[,2]
ggplot(plot,aes(x = F1,y=F2))+geom_text(aes(label=term),hjust=0, vjust=0, size=3)
#explorer des zones
ggplot(plot,aes(x = F1,y=F2))+geom_text(aes(label=term),hjust=0, vjust=0, size=3)+xlim(2,3)+ylim(0,1)
## Warning: Removed 1488 rows containing missing values (geom_text).
On peut aller plus loin et reutiliser le POS
voir https://statsmaths.github.io/stat395-f17/class16/
de plus on travaille non plus sur les occurences mais sur le TFIDF.
Finalement, le poids s’obtient en multipliant les deux mesures : la fréquence d’apparition dans un document mais aussi sa dispersion parmi les documents. Quand celle-ci est importante le poids du terme est minoré, il est moins informatif.
Pour un terme t dans un document d, le poids W(t,d) du terme dans ce document est donné par
W(t,d) = TF(t,d) log(N/DFt)
où :
La fréquence du terme (TF) est donc pondérée par l’inverse du nombre de documents (IDF) qui le contiennent. Un mot fréquent mais concentré dans quelques documents aura un poids plus important qu’un document d’égale fréquence, mais distribué dans un nombre plus grand de documents. ( voir. C’est pourquoi on parle de TFIDF. CQFJ!
#on extrait le vocabulaire
tfidf <- cnlp_get_token(obj) %>%
filter(upos %in% c("ADJ","NOUN")) %>%
cnlp_utils_tfidf()
tdm<-as.data.frame(t(as.matrix(tfidf)))
et on représente dans l’espace tsne.
tsne_out <- Rtsne(tdm, dims = 2, initial_dims = 50,
perplexity = 3, theta = 0.5, check_duplicates = FALSE,
pca = TRUE, max_iter = 300)
#plot(tsne_out$Y) #pour tester rapidement les effets de la perplexité
xy<-as.data.frame(tsne_out$Y )#extraction des coordonnee
#construction du tableau termes - coordonnée
y<-row.names(tdm)
y<-as.data.frame(y)
xy<-cbind(xy,y)
ggplot(xy,aes(x = V1,y=V2))+geom_text(aes(label=y),hjust=0, vjust=0, size=3)
Trouve-t-on la même densité de topics dans les catégories d’hôtels?
on reprend les gammas comme dans la section LDA et évolution
et on compare la distribution des topic par classes d’hôtels.
Dans cet article on aura d’abord montré qu’un corpus d’avis peut être décrit par un faisceaux d’indicateurs relatif d’une part à manière dont est exprimé le contenu et à la nature de ce qui est exprimé.
Ces critères permettent de comparer différentes classes. Dans le cas de la comparison des hotels nous avons privilégié une segmentation basique du marché entre les hotels de prestige et les plus modestes pensions. L’intérêt de cette analyse vient de ce que ces segments étant relatif
sur le plan théorique avec l’introduction de l’idée de production lanagière, pas seulement regarder ce que les gens disent, c’est l’application quotidienne dans quelques entreprises par la méthode du " sentiment by facet“, mais en completant par des indicateurs de lisibilité et de diversité lexicale, s’intéresser aussi au comment.
Ceci est d’autant plus pertinent que les consommatcteurs sont acteurs et producteurs, qu’il y a un enjeu à contrôler cette production , soit en encourageant ceux qui s’expriment le mieux, soit en censurant ceux dont les contenu sont moins qualitatifs. C’est un problème pour les plateformes qui souhaitent améliorer le contenu que par les les groupes d’intérêt ( office de tourisme, syndicat hoteliers).
Sur le plan méthodologique, cette étude a été produite en combinant un ensemble d’outils avancés d’analyses textuelle.
*un corpus mal maitrisé
des indicateurs pars toujours bien chosis
cette étude est avant tout un modèle d’analyse dont les résultats empiriques ne pourront être considéréré que si l’on répète ces analyses sur des corpus différents. Les commentaires consignés sur d’autres plateformes de réservation : booking.com en premier. Mais aussi les réseaux sociaux.
L’identification des unités d’analyses (les hôtels, mais aussi les iles) demande de meilleures ressources en matière de reconnaissance d’entités nommées (des lieux, des établissements, des personnages); existe-t-il un index adpaté à la zone étudiée? Nous apprendons que la qualité du corpus dépend aussi de la facilité à ce qu’on puisse définir ce dont il est l’objet.
Sur un plan plus technique, l’expérience conduit à espérer qu’on puisse trouver de meilleures solutions pour les tâches suivantes : * On peut d’ailleur imaginer un classificateur pour évaluer la qualité d’écriture et développer des outils plus adpaté de mesure de la lisibilité * L’exploitation syntaxique et positionnelle des données textuelles. * l’analyse des biais de sélection (propension à publier plus forte chez les satisfaits - qui répète, que chez les autres qui ne répètent pas. Dans le cadre de la polynésie il faut distinguer les touristes internationaux qui ne sont pas susceptibles de revenir (c’est la destination d’une vie) et du tourisme local alimenté principalement par les habitants de Tahiti. Dans cette population des habitudes peuvent être prises à l’égard d’une ile ou d’un établissement.
Un champs passionnant mais ambigu : la production importante et presque exhaustive rélève des ressources nouvelles pour la recherche, mais sa production est un processus social comme les autres qui dans ce cas particuliers dépend des compétences langagières des sujets qui filtre leur expérience par le travers de leurs habitudes et de leurs compétences langagières ( les habitudes sont les styles tels que les accents, les expressions toute faite, les tournures de style acquises dans son groupe culturel).
la contribution principale réside dans ce modèle simple :
expérience -> compétences -> qualité de la production textuelle -> attractivité et efficience de la plateforme
nous aurons montré qu’il y a des différences, faibles mais sensibles.
Pour le spécialiste en gestion la nécessité d’explorer ce que d’autres disciplines font. En particulier la psycho linguistique computationnelle quand elles s’intéressent à la langue vernaculaire. La particularité des corpus d’UGC est d’être rédigés dans une langue souvent mal maitrisée, idiomatique, condensée, mêlant symbôle d’expression (icones) et usage dérivé de la ponctuation. Ces spécificités demandent certainement pour améliorer la qualité de l’analyse des outils et des lexiques spécifiques, mais surtout une conceptualisation de la langue qui est insuffisante dans nos disciplines.
l’intérêt de la recherche réside dans l’attention prêtée aux facteurs qui améliorent la qualité de la production textuelle. Dans le cas des plateformes de contenu c’est d’autant plus important que cette production est le produit offert en retour pour faciliter les choix, et encourager la décision de réservation. Mieux comprendre les processus qui contribuent à sa qualité est essentiel. Quels dispositifs mettre en place ? comment les agencer ? les paramètrer.
Sur un plan concrêt ceci passe par différentes solutions. En voici un échantillon, qu’on peut répartir en deux catégories : classer pour mettre en avant le plus favorable, capaciter en donnant à ceux qui ont les capacités d’expression les plus faibles des moyens de produire une meilleur contenu. La compétition contre le care.
Classements :
Capacitation * exemples et modèles * correction orthographique, grammaticale et stylistique
finalement un dilemme entre la sincérité, l’authenticité (respect de la source), la représentativité et recherche d’une plus grande lisibilité, attractivité et positivité.
dans les moyens La compétition contre le care. l’efficacité immédiate contre la résilience du milieur.
Arnold, Taylor. 2017. “A Tidy Data Model for Natural Language Processing Using cleanNLP.” CoRR abs/1703.09570. http://arxiv.org/abs/1703.09570.
Blei, David M., Andrew Y. Ng, and Michael I. Jordan. 2003. “Latent Dirichlet Allocation.” J. Mach. Learn. Res. 3 (March): 993–1022. http://dl.acm.org/citation.cfm?id=944919.944937.
Canini, Kevin, Lei Shi, and Thomas Griffiths. 2009. “Online Inference of Topics with Latent Dirichlet Allocation.” In Proceedings of the Twelth International Conference on Artificial Intelligence and Statistics, edited by David van Dyk and Max Welling, 5:65–72. Proceedings of Machine Learning Research. Hilton Clearwater Beach Resort, Clearwater Beach, Florida USA: PMLR. http://proceedings.mlr.press/v5/canini09a.html.
Coleman, Meri, and T. L. Liau. 1975. “A Computer Readability Formula Designed for Machine Scoring.” Journal of Applied Psychology 60 (2): 283–84. doi:10.1037/h0076540.
Hu, Ya-Han, and Kuanchin Chen. 2016. “Predicting Hotel Review Helpfulness: The Impact of Review Visibility, and Interaction Between Hotel Stars and Review Ratings.” International Journal of Information Management 36 (6): 929–44. doi:10.1016/j.ijinfomgt.2016.06.003.
Hug, Marc. 2004. “La Loi de Menzerath Appliquée à Un Ensemble de Textes.” Lexicometrica. Université Paris 3.
Humphreys, Ashlee, and Rebecca Jen-Hui Wang. 2018. “Automated Text Analysis for Consumer Research.” Edited by Eileen Fischer and Linda Price. Journal of Consumer Research 44 (6): 1274–1306. doi:10.1093/jcr/ucx104.
Kramer, Adam D. I., Jamie E. Guillory, and Jeffrey T. Hancock. 2014. “Experimental Evidence of Massive-Scale Emotional Contagion Through Social Networks.” Proceedings of the National Academy of Sciences 111 (24): 8788–90. doi:10.1073/pnas.1320040111.
Mohammad, Saif M., and Peter D. Turney. 2013. “Crowdsourcing a Word-Emotion Association Lexicon.” Computational Intelligence 29 (3): 436–65.
Ordenes, Francisco Villarroel, Stephan Ludwig, Ko De Ruyter, Dhruv Grewal, and Martin Wetzels. 2017. “Unveiling What Is Written in the Stars: Analyzing Explicit, Implicit and Discourse Patterns of Sentiment in Social Media.” Journal of Consumer Research, January, ucw070. doi:10.1093/jcr/ucw070.
Pekar, Viktor, and Shiyan Ou. 2008. “Discovery of Subjective Evaluations of Product Features in Hotel Reviews.” Journal of Vacation Marketing 14 (2): 145–55. doi:10.1177/1356766707087522.
Plutchik, Robert. 1982. “A Psychoevolutionary Theory of Emotions.” Social Science Information 21 (4-5): 529–53. doi:10.1177/053901882021004003.
Senter, R.J. 1967. “Automated Readability Index,” November. Wright-Patterson Air Force Base: iii. AMRL-TR-6620.
Šuster, Simon. 2015. “An Investigation into Language Complexity of World-of-Warcraft Game-External Texts.” ArXiv:1502.02655 [Cs], February. http://arxiv.org/abs/1502.02655.
Tweedie, Fiona J., and R. Harald Baayen. 1998. “How Variable May a Constant Be? Measures of Lexical Richness in Perspective.” Computers and the Humanities 32: 323–52.