Skip to content

NederlandsMD/Python---Sentiment-Analysis-News-Org-Twitter-API

Repository files navigation

Sentiment Analysis of Major News Organizations' Twitter Feeds

Observation 1: Fox News has been the most positive news organization, CNN the most negative, over the last 100 tweets
Observation 2: The same media organizations that come closest to extreme negative tweets (-1.0) also come the closest to extreme positive tweets (+1.0)
Observation 3: The New York Times seems to be the most moderate tweeter (or balance negative with positive), with an average polarity score of -0.01 over the past 100 tweets

#Import Dependencies
import tweepy
import numpy as np
import pandas as pd
from pprint import pprint
import matplotlib.pyplot as plt
from matplotlib import style
style.use('ggplot')
from datetime import datetime

# Import and Initialize Sentiment Analyzer
from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
analyzer = SentimentIntensityAnalyzer()

# Twitter API Keys
from config import (consumer_key, 
                    consumer_secret, 
                    access_token, 
                    access_token_secret)

# Setup Tweepy API Authentication
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth, parser=tweepy.parsers.JSONParser())
# Get the last 100 tweets for each news org, analyze with VADER, store it in a dataframe
news_orgs = ("@BBCBreaking", "@CBSNews", "@cnnbrk", "@FoxNews", "@nytimes")

oldestTweet = None
News_Sense_df = pd.DataFrame()

for org in news_orgs:
    oldest_tweet = None
   
    sentiments = []
    tweet_times = []
    
    for x in range(1, 6):
        public_tweets = api.user_timeline(org,
                                          page=x, 
                                          result_type="recent", 
                                          tweet_mode="extended",
                                          max_id = oldest_tweet)
        for tweet in public_tweets:
            sent_result = analyzer.polarity_scores(tweet["full_text"])
            sentiments.append(sent_result["compound"])
            tweet_times.append(tweet["created_at"])
            oldest_tweet = tweet["id"] - 1
            
    News_Sense_df[org + "_sents"] = sentiments
    News_Sense_df[org + "_ttime"] = tweet_times
            
News_Sense_df.head()
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
</style>
@BBCBreaking_sents @BBCBreaking_ttime @CBSNews_sents @CBSNews_ttime @cnnbrk_sents @cnnbrk_ttime @FoxNews_sents @FoxNews_ttime @nytimes_sents @nytimes_ttime
0 0.6688 Sat Jul 14 16:23:05 +0000 2018 -0.8402 Sun Jul 15 02:03:04 +0000 2018 -0.6705 Sun Jul 15 02:02:36 +0000 2018 -0.4939 Sun Jul 15 02:15:58 +0000 2018 0.0000 Sun Jul 15 02:13:14 +0000 2018
1 -0.0516 Sat Jul 14 15:52:16 +0000 2018 0.0000 Sun Jul 15 01:48:04 +0000 2018 -0.7964 Sat Jul 14 22:15:27 +0000 2018 0.5574 Sun Jul 15 02:05:17 +0000 2018 0.5423 Sun Jul 15 01:56:10 +0000 2018
2 0.0000 Sat Jul 14 14:34:06 +0000 2018 -0.8402 Sun Jul 15 01:40:07 +0000 2018 0.7717 Sat Jul 14 16:52:18 +0000 2018 0.0000 Sun Jul 15 02:02:58 +0000 2018 0.0000 Sun Jul 15 01:39:40 +0000 2018
3 -0.4753 Fri Jul 13 18:47:11 +0000 2018 -0.6486 Sun Jul 15 01:33:03 +0000 2018 0.7717 Sat Jul 14 16:31:12 +0000 2018 0.0000 Sun Jul 15 01:50:28 +0000 2018 -0.4404 Sun Jul 15 01:23:20 +0000 2018
4 -0.7906 Fri Jul 13 16:46:13 +0000 2018 -0.6486 Sun Jul 15 01:18:03 +0000 2018 0.0000 Sat Jul 14 16:03:24 +0000 2018 0.8588 Sun Jul 15 01:33:49 +0000 2018 -0.8555 Sun Jul 15 01:07:13 +0000 2018
# Get the average sentiment of the last 100 tweets for each news organization, store in a dataframe
average_sent = []

for org in news_orgs:
    avg_sent = News_Sense_df[org + "_sents"].mean()
    average_sent.append(avg_sent)

news_orgs_present = ("BBC", "CBS", "CNN", "Fox", "NYT")
Averages_df = pd.DataFrame({"Organization" : news_orgs_present,
                           "Average Sentiment": average_sent})
Averages_df = Averages_df[["Organization", "Average Sentiment"]]
Averages_df
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
</style>
Organization Average Sentiment
0 BBC -0.116790
1 CBS -0.130990
2 CNN -0.100812
3 Fox 0.066101
4 NYT -0.010673
# Plot the sentiments chart
plt.figure(figsize=(10,7))
plt.scatter(np.arange(0,100,1),News_Sense_df["@BBCBreaking_sents"], alpha=0.9, facecolors="skyblue", edgecolors="black", label="BBC")
plt.scatter(np.arange(0,100,1),News_Sense_df["@CBSNews_sents"], alpha=0.9, facecolors="green", edgecolors="black", label="CBS")
plt.scatter(np.arange(0,100,1),News_Sense_df["@cnnbrk_sents"], alpha=0.9, facecolors="red", edgecolors="black", label="CNN")
plt.scatter(np.arange(0,100,1),News_Sense_df["@FoxNews_sents"], alpha=0.9, facecolors="blue", edgecolors="black", label="Fox")
plt.scatter(np.arange(0,100,1),News_Sense_df["@nytimes_sents"], alpha=0.9, facecolors="yellow", edgecolors="black", label="New York Times")
plt.xlim(101,-1)
plt.xlabel("Tweets Ago", fontsize=14)
plt.yticks(np.arange(-1, 1.4, step=0.5))
plt.ylim(-1.1,1.1)
plt.ylabel("Tweet Polarity", fontsize=14)
plt.tick_params(axis='both', which='major', labelsize=14)
analysis_date = datetime.now()
date = datetime.strftime(analysis_date, '%m/%d/%Y')
plt.title(f"Sentiment Analysis of Media Tweets ({date})")
leg = plt.legend(bbox_to_anchor=(1.22,1), loc="upper right", frameon=1)
frame = leg.get_frame()
frame.set_facecolor('white')
frame.set_edgecolor('white')
leg.set_title("Media Sources", prop = {'size':'12'})
plt.savefig("Media Sentiment Analysis_100 Tweets.png", bbox_inches="tight")
plt.show()

png

plt.figure(figsize=(10,7))
my_colors = ["skyblue", "green", "red", "blue", "yellow"]
plt.bar(news_orgs_present, average_sent, alpha=1, edgecolor="black", width=1, color=my_colors)
plt.grid(False)
plt.ylim(min(average_sent) - 0.025, max(average_sent) + 0.025)
plt.ylabel("Tweet Polarity", fontsize=14)
plt.tick_params(axis='both', which='major', labelsize=14)
for x, y in enumerate(average_sent):
    if y > 0.0:
        plt.text(x-0.15, y + .015, "+" + str(round(y,2)), color='black', fontsize=14)
    else:
        plt.text(x-0.15, y - .015, str(round(y,2)), color='black', fontsize=14) 

plt.title(f"Overall Media Sentiment based on Twitter ({date})")
plt.savefig("Average Media Sentiment.png")

png

About

Python, Matplotlib sentiment analysis of various major news outlets using Twitter API.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors