<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Setup
Step1:  Tweet activity
Let's explore counts by hour, day of the week, and weekday versus weekend hourly trends.
Step2:  Hmmm, what's this created_at attribute?
Step3:  Hourly counts
Step4:  Because there are hours of the day where there are no tweets, one must explicitly add any zero-count hours to the index.
Step5:  Day of the week counts
Step6:  Weekday vs weekend hourly counts
Step7:  Visualize tweet counts
By hour
Step8:  Let's see if we can "fancy-it-up" a bit by making it 538 blog-like. Note
Step9:  By day of the week
Step10:  By weekday and weekend
<ASSISTANT_TASK:>
Python Code:
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use('fivethirtyeight')
import tweepy
import numpy as np
import pandas as pd
from collections import Counter
from datetime import datetime
# Turn on retina mode for high-quality inline plot resolution
from IPython.display import set_matplotlib_formats
set_matplotlib_formats('retina')
# Version of Python
import platform
platform.python_version()
# Import Twitter API keys
from credentials import *
# Helper function to connect to Twitter API
def twitter_setup():
    auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
    auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)
    
    api = tweepy.API(auth)
    return api
# Extract Twitter data
extractor = twitter_setup()
# Twitter user
twitter_handle = 'fastforwardlabs'
# Get most recent two hundred tweets
tweets = extractor.user_timeline(screen_name=twitter_handle, count=200)
print('Number of tweets extracted: {}.\n'.format(len(tweets)))
Explanation: Setup
End of explanation
# Inspect attributes of tweepy object
print(dir(tweets[0])) # look at the first element/record
Explanation: Tweet activity
Let's explore counts by hour, day of the week, and weekday versus weekend hourly trends.
End of explanation
# What format is it in? answer: GMT, according to Twitter API
print(tweets[0].created_at)
# Create datetime index: convert to GMT then to Eastern daylight time EDT
tweet_dates = pd.DatetimeIndex([tweet.created_at for tweet in tweets], tz='GMT').tz_convert('US/Eastern')
Explanation: Hmmm, what's this created_at attribute?
End of explanation
# Count the number of tweets per hour
num_per_hour = pd.DataFrame( { 'counts': Counter(tweet_dates.hour) })
# Create hours data frame
hours = pd.DataFrame({'hours': np.arange(24)})
Explanation: Hourly counts:
End of explanation
# Merge data frame objects on common index, peform left outer join and fill NaN with zero-values
hour_counts = pd.merge(hours, num_per_hour, left_index=True, right_index=True, how='left').fillna(0)
hour_counts
Explanation: Because there are hours of the day where there are no tweets, one must explicitly add any zero-count hours to the index.
End of explanation
# Count the number of tweets by day of the week
num_per_day = pd.DataFrame( { 'counts': Counter(tweet_dates.weekday) })
# Create days data frame
days = pd.DataFrame({'day': np.arange(7)})
# Merge data frame objects on common index, perform left outer join and fill NaN with zero-values
daily_counts = pd.merge(days, num_per_day, left_index=True, right_index=True, how='left').fillna(0)
Explanation: Day of the week counts:
End of explanation
# Flag the weekend from weekday tweets
weekend = np.where(tweet_dates.weekday < 5, 'weekday', 'weekend')
# Construct multiply-indexed DataFrame obj indexed by weekday/weekend and by hour
by_time = pd.DataFrame([tweet.created_at for tweet in tweets], 
                       columns=['counts'],
                       index=tweet_dates).groupby([weekend, tweet_dates.hour]).count() 
# Optionally, set the names attribute of the index
by_time.index.names=['daytype', 'hour']
# Show two-dimensional view of multiply-indexed DataFrame
by_time.unstack()
# Merge DataFrame on common index, perform left outer join and fill NaN with zero-values
by_time = pd.merge(hours, by_time.unstack(level=0), left_index=True, right_index=True, how='left').fillna(0)
# Show last five records
by_time.tail()
Explanation: Weekday vs weekend hourly counts:
End of explanation
# Optional: Create xtick labels in Standard am/pm time format
xticks = pd.date_range('00:00', '23:00', freq='H', tz='US/Eastern').map(lambda x: pd.datetime.strftime(x, '%I %p'))
Explanation: Visualize tweet counts
By hour:
End of explanation
%%javascript
IPython.OutputArea.prototype._should_scroll = function(lines) {
    return false;
}
# Plot
ax = hour_counts.plot(x='hours', y='counts', kind='line', figsize=(12, 8))
ax.set_xticks(np.arange(24))
#ax.set_xticklabels(xticks, rotation=50)
#ax.set_title('Number of Tweets per hour')
#ax.set_xlabel('Hour')
#ax.set_ylabel('No. of Tweets')
#ax.set_yticklabels(labels=['0  ', '5  ', '10  ', '15  ', '20  ', '25  ', '30  ', '35  ', '40  '])
ax.tick_params(axis='both', which='major', labelsize=14)
ax.axhline(y=0, color='black', linewidth=1.3, alpha=0.7)
ax.set_xlim(left=-1, right=24)
ax.xaxis.label.set_visible(False)
now = datetime.strftime(datetime.now(), '%a, %Y-%b-%d at %I:%M %p EDT')
ax.text(x=-2.25, y=-5.5,
    s = u"\u00A9" + 'THE_KLEI                                                {}                        Source: Twitter, Inc.   '.format(now),
    fontsize=14, color='#f0f0f0', backgroundcolor='grey')
ax.text(x=-2.35, y=44, s="When does @{} tweet? - time of the day".format(twitter_handle),
               fontsize=26, weight='bold', alpha=0.75)
ax.text(x=-2.35, y=42, 
               s='Number of Tweets per hour based-on 200 most-recent tweets as of {}'.format(datetime.strftime(datetime.now(), '%b %d, %Y')),
              fontsize=19, alpha=0.85)
plt.show()
Explanation: Let's see if we can "fancy-it-up" a bit by making it 538 blog-like. Note: The following cell disables notebook autoscrolling for long outputs. Otherwise, the notebook will embed the plot inside a scrollable cell, which is more difficult to read the plot.
End of explanation
# Plot
daily_counts.index = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']
daily_counts['counts'].plot(title='Daily tweet counts', figsize=(12, 8), legend=True)
plt.show()
Explanation: By day of the week:
End of explanation
%%javascript
IPython.OutputArea.prototype._should_scroll = function(lines) {
    return false;
}
# Plot
fig, ax = plt.subplots(2, 1, figsize=(14, 12))
# weekdays
by_time.loc[:, [('counts', 'weekday')]].plot(ax=ax[0], title='Weekdays', kind='line')
# weekends
by_time.loc[:, [('counts', 'weekend')]].plot(ax=ax[1], title='Weekend', kind='line')
ax[0].set_xticks(np.arange(24))
#ax[0].set_xticklabels(xticks, rotation=50)
ax[1].set_xticks(np.arange(24))
#ax[1].set_xticklabels(xticks, rotation=50)
plt.show()
Explanation: By weekday and weekend:
End of explanation
<END_TASK>