If there is one thing that can be safely argued in these post-election days, it is that I need to get out of my liberal echo chamber. To that purpose, I tried to get into the minds of the presumably triumphant feeling Donald Trump supporters via the #MakeAmericaGreatAgain hashtag. It was not surpising to find mostly positive sentiment in the texts but I was most interested in what is still bothering them.
First I load all the necessary libraries.
library(twitteR)
library(tidytext)
library(stringr)
library(ggplot2)
library(dplyr)
library(wordcloud)
library(RColorBrewer)
Setting up Twitter authentication.
## [1] "Using direct authentication"
Next, I import tweets with the #MakeAmericaGreatAgain hashtag.
num_tweets <- 1000
repub <- searchTwitter('#MakeAmericaGreatAgain', n = num_tweets)
head(repub)
## [[1]]
## [1] "RebelACole: RT @MightyBusterBro: Anti-Trump\nPROTEST RIOTS VIDEO:\nThe ORGANIZERS\nand the FUNDERS\n\n#Soros #Globalism #TrumpRiots #MakeAmericaGreatAgain #…"
##
## [[2]]
## [1] "4DC4USA: RT @WeNeedTrump: The fun is just getting started. Congratulations to Steve Bannon and Reince Priebus! #MakeAmericaGreatAgain https://t.co/s…"
##
## [[3]]
## [1] "MorrisSaltikoff: RT @americvntrvmp: Trump race car spotted in Houston #Texas\n#MakeAmericaGreatAgain https://t.co/yrKHDh0hOx"
##
## [[4]]
## [1] "debbie_groves1: RT @JrcheneyJohn: Boycott the #CorruptMedia They see Shills for the Democrat Party #DrainTheSwamp and #MakeAmericaGreatAgain \nhttps://t.co/…"
##
## [[5]]
## [1] "karinsabatini1: RT @tponews: A Plea for Unity: I dedicate this to all Hillary supporters and hope we can all come together and #MakeAmericaGreatAgain #NotM…"
##
## [[6]]
## [1] "mackette52: NEVER FORGET \n\n @glennbeck STARTED this SMEAR!\n\n#boycottBeck \n\n@realDonaldTrump \n#MakeAmericaGreatAgain… https://t.co/VwWnKszhg2"
Next, I turn the list into a dataframe.
repub_df <- twListToDF(repub)
head(repub_df)
## text
## 1 RT @MightyBusterBro: Anti-Trump\nPROTEST RIOTS VIDEO:\nThe ORGANIZERS\nand the FUNDERS\n\n#Soros #Globalism #TrumpRiots #MakeAmericaGreatAgain #…
## 2 RT @WeNeedTrump: The fun is just getting started. Congratulations to Steve Bannon and Reince Priebus! #MakeAmericaGreatAgain https://t.co/s…
## 3 RT @americvntrvmp: Trump race car spotted in Houston #Texas\n#MakeAmericaGreatAgain https://t.co/yrKHDh0hOx
## 4 RT @JrcheneyJohn: Boycott the #CorruptMedia They see Shills for the Democrat Party #DrainTheSwamp and #MakeAmericaGreatAgain \nhttps://t.co/…
## 5 RT @tponews: A Plea for Unity: I dedicate this to all Hillary supporters and hope we can all come together and #MakeAmericaGreatAgain #NotM…
## 6 NEVER FORGET \n\n @glennbeck STARTED this SMEAR!\n\n#boycottBeck \n\n@realDonaldTrump \n#MakeAmericaGreatAgain… https://t.co/VwWnKszhg2
## favorited favoriteCount replyToSN created truncated
## 1 FALSE 0 <NA> 2016-11-14 04:47:27 FALSE
## 2 FALSE 0 <NA> 2016-11-14 04:47:16 FALSE
## 3 FALSE 0 <NA> 2016-11-14 04:47:14 FALSE
## 4 FALSE 0 <NA> 2016-11-14 04:47:14 FALSE
## 5 FALSE 0 <NA> 2016-11-14 04:47:10 FALSE
## 6 FALSE 0 <NA> 2016-11-14 04:47:08 TRUE
## replyToSID id replyToUID
## 1 <NA> 798024522230272006 <NA>
## 2 <NA> 798024476059283456 <NA>
## 3 <NA> 798024470355005440 <NA>
## 4 <NA> 798024467792338944 <NA>
## 5 <NA> 798024450578886657 <NA>
## 6 <NA> 798024442626658304 <NA>
## statusSource
## 1 <a href="http://twitter.com/#!/download/ipad" rel="nofollow">Twitter for iPad</a>
## 2 <a href="http://twitter.com/download/android" rel="nofollow">Twitter for Android</a>
## 3 <a href="http://twitter.com" rel="nofollow">Twitter Web Client</a>
## 4 <a href="http://twitter.com/download/iphone" rel="nofollow">Twitter for iPhone</a>
## 5 <a href="http://twitter.com/download/iphone" rel="nofollow">Twitter for iPhone</a>
## 6 <a href="http://twitter.com/download/android" rel="nofollow">Twitter for Android</a>
## screenName retweetCount isRetweet retweeted longitude latitude
## 1 RebelACole 1412 TRUE FALSE <NA> <NA>
## 2 4DC4USA 688 TRUE FALSE <NA> <NA>
## 3 MorrisSaltikoff 3 TRUE FALSE <NA> <NA>
## 4 debbie_groves1 186 TRUE FALSE <NA> <NA>
## 5 karinsabatini1 52 TRUE FALSE <NA> <NA>
## 6 mackette52 0 FALSE FALSE <NA> <NA>
To be able to analyze the text for sentiment, I had to tidy the text. To get a feel for the most common words being used in the #MakeAmericaGreatAgain tweets, I ran frequencies for the top 20 words.
reg <- "([^A-Za-z\\d#@']|'(?![A-Za-z\\d#@]))"
repub_words <- repub_df %>% filter(!str_detect(text, '^"')) %>% mutate(text = str_replace_all(text, "https://t.co/[A-Za-z\\d]+|&", "")) %>% unnest_tokens(word, text, token = "regex", pattern = reg) %>% filter(!word %in% stop_words$word, str_detect(word, "[a-z]"))
repub_words %>% group_by(word) %>% summarize(n = n()) %>% arrange(desc(n)) %>% top_n(20)
## # A tibble: 20 × 2
## word n
## <chr> <int>
## 1 #makeamericagreatagain 979
## 2 rt 696
## 3 trump 247
## 4 @realdonaldtrump 122
## 5 congratulations 110
## 6 bannon 109
## 7 reince 102
## 8 video 89
## 9 @weneedtrump 81
## 10 #soros 71
## 11 protest 71
## 12 #maga 70
## 13 anti 70
## 14 https 69
## 15 @mightybusterbro 68
## 16 #globalism 68
## 17 #trumpriots 68
## 18 funders 68
## 19 organizers 68
## 20 riots 68
Since most of the above returned words do not have much meaning I will do a sentiment analysis to start unpacking how Trump supporters are feeling vis-a-vis their tweets.
nrc <- sentiments %>% filter(lexicon == "nrc") %>% select(word, sentiment)
Running frequencies on sentiment paints a better picture. As I could have predicted the most common sentiments are positive but I am intrigued to learn more about what could still be getting Trump supporters down.
repub_words_sentiments <- repub_words %>% inner_join(nrc, by = "word")
repub_words_sentiments %>% group_by(sentiment) %>% summarize(n = n()) %>% arrange(desc(n))
## # A tibble: 10 × 2
## sentiment n
## <chr> <int>
## 1 positive 607
## 2 anticipation 458
## 3 trust 433
## 4 surprise 376
## 5 negative 343
## 6 joy 336
## 7 sadness 238
## 8 fear 220
## 9 anger 191
## 10 disgust 94
To learn more, I am going to make a wordcloud of just the “sadness” coded words.
cloud_sadness <- brewer.pal(8,"Set1")
repub_words_sentiments %>% filter(sentiment == "sadness") %>% count(word) %>% with(wordcloud(word, n, max.words = 75, scale=c(5,.5),min.freq=1, random.order=FALSE, rot.per=.15, colors=brewer.pal(8,"Set1")), rot.per=0.35)
I am confused by the strong presence of the word “vote”. The sentiment calculations begin to show their limitations in coding human emotions vis-a-vis words.
Next, I am curious about what topics are bringing Trump supporters joy. Again, “vote” makes an unexpected appearance.
cloud_joy <- brewer.pal(8,"Set1")
repub_words_sentiments %>% filter(sentiment == "joy") %>% count(word) %>% with(wordcloud(word, n, max.words = 75, scale=c(5,.5),min.freq=1, random.order=FALSE, rot.per=.15, colors=brewer.pal(8,"Set1")), rot.per=0.35)
Finally, I was curious what might be causing Trump supporters fear and found it humorous that “god” showed up in this word cloud. Certainly, the word god could strike fear in someone but I am assumng it was used in the positive, self-righteous sense in this context.
cloud_fear <- brewer.pal(8,"Set1")
repub_words_sentiments %>% filter(sentiment == "fear") %>% count(word) %>% with(wordcloud(word, n, max.words = 75, scale=c(5,.5),min.freq=1, random.order=FALSE, rot.per=.15, colors=brewer.pal(8,"Set1")), rot.per=0.35)
Finally, I would like to look at sentiment and its relationship to percent of retweets.
To begin, I have to filter out tweets that were actually retweeted.
retweets <- filter(repub_words_sentiments, retweetCount >1)
To get a quick snapshot, I create a table summarizing retweets by sentiment
retweets %>% group_by(sentiment) %>% summarize(n = n()) %>% arrange(desc(n))
## # A tibble: 10 × 2
## sentiment n
## <chr> <int>
## 1 positive 409
## 2 anticipation 379
## 3 surprise 306
## 4 trust 299
## 5 negative 253
## 6 joy 248
## 7 sadness 193
## 8 fear 175
## 9 anger 145
## 10 disgust 60
The data would be more meaningful if a percent of retweets is calculated and graphed.
retweets_sent <- retweets %>% group_by(sentiment) %>% summarize(n = n()) %>% mutate(percent_of_retweets = n/sum(n))
ggplot(retweets_sent, aes(x=sentiment, y= percent_of_retweets, fill=sentiment)) + geom_bar(stat = "identity", position = "dodge") + scale_fill_brewer(palette="Paired") + labs(x="sentiments", y="Percent of retweets") + theme(axis.text.x = element_text(angle = 90, hjust = 1))
It looks as though tweets with positive sentiments are more likely to be retweeted and thus it could be argued that the general sentiments that Trump supporters are gravitating to and expressing are more positive.