https://ithaka-labs.s3.amazonaws.com/static-files/images/tdm/tdmdocs/CC_BY.png

Created by Nathan Kelber and Ted Lawless for JSTOR Labs under Creative Commons CC BY License
For questions/comments/improvements, email nathan.kelber@ithaka.org.


Sentiment Analysis with VADER

Description: This notebook describes Sentiment Analysis and demonstrates a basic application using the algorithm VADER (Valence Aware Dictionary for sEntiment Reasoning).

Use Case: For Learners (Detailed explanation, not ideal for researchers)

Difficulty: Beginner

Completion Time: 30 minutes

Knowledge Required:

Knowledge Recommended: None

Data Format: None

Libraries Used: vaderSentiment

Research Pipeline: None


Methods for Sentiment Analysis

Sentiment analysis can help an analyst discover whether feedback is positive, negative, or mixed. For example, a large company like Amazon or Walmart could use sentiment analysis on user reviews to determine whether a featured product should be promoted or discontinued. Sentiment analysis generally falls into two categories:

  • Rule-based algorithms

  • Machine Learning models

Rule-Based Algorithms

Rule-based algorithms assign sentiment scores to particular words or multi-word constructions. Simple algorithms may simply assess each word individually in a feedback document and add up an overall score. More complex algorithms may assess multi-word (or n-gram) constructions and have special rules for addressing issues such as negation, emojis, and emoticons. They can detect the difference between “bad”, “not bad”, and “bad ass” as well as “=)” and “:^(”.

Machine Learning Models

Machine learning models rely on feedback data that has already been assessed by humans to have a particular sentiment. Each piece of feedback is labeled by a human reader who may place the feedback into a particular category. The categories could be as simple as positive, negative, or neutral. As long as there exists labeled data, a machine learning model can often identify complex concepts. For example, a car manufacturer may desire to classify the sentiment of feedback from past buyers as: “budget-conscious”, “eco-conscious”, “tech-enthusiastic”, “luxury-driven”, “performance-driven”, etc. Assuming there is an adequately labeled training data for each of these categories, a machine learning model could assign a score for each category. This could help analysts understand the brand better, answering questions about what consumers do or do not like about a particular vehicle.

In the humanities, sentiment analysis could be used to track emerging trends on social media. For example, we might ask: “How are Twitter or Reddit users responding to a particular government policy or public event?”

VADER

This notebook uses a rule-based algorithm named VADER (Valence Aware Dictionary and sEntiment Reasoner). VADER is a rule-based algorithm that is “specifically attuned to sentiments expressed in social media.” It relies on a specialized lexicon of words, phrases, and emojis. Each token in the lexicon is assigned a “mean-sentiment rating” between -4 (extremely negative) to 4 (extremely positive). Here are a few examples:

Token

Mean-Sentiment Rating

(:

2.2

/:

-1.3

):<

-1.9

rotflmao

2.8

aghast

-1.9

awesome

3.1

awful

-2.0

There are over 7500 tokens listed in VADER lexicon. (You can also add your own if you like.) VADER also considers grammatical and syntactical rules to measure intensity based on word order and sensitive relationships between terms. For example, it increases or decreases a sentiment based on degree modifers such as: “The product is good” versus “the product is very good” versus “the product is marginally good.” To read more about VADER, including how it works and to see its code, visit the github page.

Applying the VADER Algorithm

First, we need to import the SentimentIntensityAnalyzer. Here we assign the VADER lexicon object to a variable sa.

# Import the SentimentIntensityAnalyzer
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer

# Creat the variable sa to hold the VADER lexicon object 
sa = SentimentIntensityAnalyzer()

We can preview the contents of the lexicon by using sa.lexicon. This will return a dictionary, where each key is a token and each value is a sentiment rating.

# Preview the lexicon contents
# There are over 7500 tokens in the lexicon
sa.lexicon

In order to do our analysis, we will use a very small sample of 8 user reviews. Each review is a simple text string inside a list variable called product_reviews.

# Define a list of product reviews

product_reviews = [
    'I love this product. It helps me get so much work done. I tell everyone about what a great thing it is.',
    'This product is defective. I feel like it is broken because it does not do what it promises. Do not buy this.',
    'Do yourself a favor and buy this product as soon as possible. I recommend it to everyone I know. It has saved me so much time!',
    'This product is overpriced and useless. It was a waste of money and it made all my hair fall out.',
    'Works like a dream and it is a bargain! It solves my problems with ease. I bought two!',
    'Do not buy! This product is a ripoff. I wish it was better, but it fails constantly. What a mistake!',
    'This thing is garbage. Do yourself a favor and save the money. Mine is a dumpster fire and fell apart.',
    'I adore this product. =) It makes my life so much easier. And it is a deal!'
]

Now we will analyze each product and assign it a “normalized, weighted composite score” based on summing the valence scores of each word in the lexicon (with some adjustments based on word order and other rules). VADER measures the proportion of text that falls into positive, negative, and neutral sentiment. The result is a sentiment score that falls between -1 (the most negative) and +1 (the most positive). (This is different from the lexicon scores that fall between -4 to +4!)

# For each review in our `product_reviews` list
# Store a polarity score in `scores`
# Then print the score followed by the review
for review in product_reviews:
    scores = sa.polarity_scores(review)
    print(scores['compound'], review)

Our simple analysis does a fairly good job of assessing positive and negative sentiment. Notice that our second to last review was not very accurate:

0.5423 This thing is garbage. Do yourself a favor and save the money. Mine started on fire and fell apart.

The VADER lexicon contains the following entries:

Token

Mean-Sentiment Rating

favor

1.7

fire

-1.4

but it does not have entries for “fell apart”, “money”, or “garbage”. If a specific token is not found in the VADER lexicon, it is considered to be neutral. Like any other statistical approach, the process benefits from having more data. In this case, the sentences are very short and several significant words do not happen to exist in our lexicon.

Adding Tokens to the VADER Lexicon

The sa.lexicon is a simple dictionary, so we can add words that we want included. There are some guidelines for best scoring practices included in the academic paper linked on VADER’s github repository. (Remember that lexicon tokens are scored from -4 to +4.)

# Adding the dictionary of `new_words`
# to sa.lexicon

new_words = {
    'garbage': -2.0,
    'dumpster': -3.1,
}

sa.lexicon.update(new_words)

Let’s try our analysis again with the new lexicon.

# For each review in our `product_reviews` list
# Store a polarity score in `scores`
# Then print the score followed by the review

for review in product_reviews:
    scores = sa.polarity_scores(review)
    print(scores['compound'], review)