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]+|&amp;", "")) %>% 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

Sentimental Word Clouds

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)

Sentiment and Retweets

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.