How Twitter Feels About Bitcoin

Project type

Sentiment Analysis · Text Mining · R

Team

Individual

Skills & Tools Used:

  • R
  • tidytext
  • syuzhet (NRC lexicon)
  • Bing lexicon
  • tm
  • wordcloud
Overview

An executive team was weighing an investment in Bitcoin and wanted to know how the market felt about it. I ran a sentiment analysis on Bitcoin tweets to measure emotion and tone, and turned it into a recommendation.

Key results
3,794positive-sentiment words vs. 2,193 negative
2,410anticipation signals, the strongest emotion in the data
2,383trust signals, close behind anticipation
2lexicons compared: NRC emotions and Bing positive/negative
The question

Is public conversation about Bitcoin optimistic or fearful, and what words drive each side?

What I did
  • Built a term-document matrix and charted the most frequent words, plus a word cloud
  • Scored every tweet against the NRC lexicon (syuzhet) across eight emotions
  • Tokenized the text with tidytext and joined it to the Bing lexicon to rank the top positive and negative words
  • Translated the results into an investment recommendation for executives
What I found

Positive language outweighed negative by a wide margin, led by anticipation and trust. The top negative words (crash, lost, risk, scam) point to the fears to watch. I recommended entering while interest was high and treating dips as buying opportunities, while monitoring negative sentiment as an early warning.

The Code

The actual R I wrote for this project. Scroll inside the window to read it all.

install.packages("tm")
install.packages("SnowballC")
install.packages("wordcloud")
install.packages("RColorBrewer")
install.packages("syuzhet")
install.packages("tidytext")
install.packages("tidyverse")

library("tm")
library("SnowballC")
library("wordcloud")
library("RColorBrewer")
library("syuzhet")
library("tidytext")
library("tidyverse")



tweets <- read.csv("Desktop/tweets.csv", header= TRUE, sep = ",", quote = '"')
tweets
head(tweets)
summary(tweets)

##### term document matrix #### 

dtm <- TermDocumentMatrix(tweets)
dtm_m <- as.matrix(dtm)

#sort by decreasing value of frequency
dtm_s <- sort(rowSums(dtm_m), decreasing = TRUE)
dtm_d <-data.frame(word = names(dtm_s), freq = dtm_s)

#display top 10 most frequent words
head(dtm_d, 10)

#plotting top 10 words
barplot(dtm_d[1:10,]$freq, las = 2, names.arg = dtm_d[1:10,]$word,
        col = "lightgreen", main = "top 10 most frequent words",
        ylab = "word frequencies")


########## word cloud ##########

set.seed(1234)

wordcloud(words = dtm_d$word, freq = dtm_d$freq, min.freq = 5, 
          max.words = 100, random.order = FALSE, rot.per = 0.4, 
          colors = brewer.pal(8, "Dark2"))

########### Sentiment Analysis: part 1 ##########
#Syuzhet package
colnames(tweets)

text_reviews <- tibble(text = str_to_lower(tweets$text))

text_emo <- get_nrc_sentiment(text_reviews$text)
text_emo

text_emo_sum <- colSums(text_emo)
text_emo_sum

text_emo_df <- data.frame(count = text_emo_sum, 
                          text_emo = names(text_emo_sum))
text_emo_df

#### create bar plot ####

ggplot(text_emo_df, aes(x= reorder(text_emo,-count), 
                        y= count)) + geom_bar(stat = 'identity')


########## sentiment analysis: part 2 ##########
#bing lexicon

bing_counts <- text_reviews %>% unnest_tokens(output = word,input = text)
bing_counts

bing_counts <- text_reviews %>%
  unnest_tokens(output = word,input = text) %>%
  inner_join(get_sentiments("bing")) %>%
               count(word,sentiment,sort=TRUE)

bingtop <- bing_counts %>% group_by(sentiment) %>%
  slice_max(order_by = n, n=10) %>% 
  ungroup() %>%
  mutate(word= reorder(word,n))
bingtop

bingtop %>% ggplot(aes(word,n, fill= sentiment))+
  geom_col(show.legend = FALSE)+
  facet_wrap(~sentiment, scales = "free_y")+ labs(y= "contribution to sentiment",x= NULL)+
  coord_flip()