Feeding models with realtime streaming data
===========================================
In this example, we’ll construct a very simple model of the number of
posts relating to a given topic on twitter timelines around the world.
We’ll feed the model with live streaming data from the twitter API and
run the model in real time.
##Ingredients
Libraries
^^^^^^^^^
In addition to our standard data analytics stack, we’ll take advantage
of the `tweepy `__ library for
interacting with the twitter API, the standard python library for
dealing with `JSON `__
objects, and the standard python
`threading `__
library, to give us access to both the stream and the plots in real
time.
.. code:: ipython3
%pylab
import tweepy
import json
import pysd
import threading
from matplotlib import animation
.. parsed-literal::
Using matplotlib backend:
Populating the interactive namespace from numpy and matplotlib
Twitter Credentials
^^^^^^^^^^^^^^^^^^^
If you want to execute this recipe, you’ll need to `sign up for a
twitter developer account `__ and create a
file containing your credentials.
Name this file ``_twitter_credentials.py`` and save it in the working
directory. It should contain something similar to:
::
consumer_key = 'sdjfhkdgjhsk8u09wejne4vdj8j34'
consumer_secret = 'nvjsdv8wp43nneri'
access_token = 'vndisoerihosfdbuttonmashingjkfdlasnvei'
access_token_secret = 'navdjewrjodfjkmorebuttonmashingnjkasdoinv'
We can load these into our environment using the ``import *`` syntax.
.. code:: ipython3
from _twitter_credentials import *
::
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
/tmp/ipykernel_22050/1999121466.py in
----> 1 from _twitter_credentials import *
ModuleNotFoundError: No module named '_twitter_credentials'
Model
^^^^^
Our model is a simple delay process. The inflow of the process is the
rate at which twitter users post messages containing our keywords, and
the level decays over time as posts fall out of the top of users
timelines.
We’ll explicitly set the timescale in this demo, to show the behavior of
the system in a short timeperiod.
.. code:: ipython3
model = pysd.read_vensim('../../models/Twitter/Twitter.mdl')
model.set_components({'displacement_timescale':30})
The Recipe
----------
Listening to twitter
^^^^^^^^^^^^^^^^^^^^
The first thing we’ll do is to create a variable that will track the
total number of posts recieved in the last model interation timeperiod.
This counter will be reset after every model timestep.
.. code:: ipython3
counter = 0
Next, we’ll construct a function that will be run whenever a tweet is
recieved from the API. This function will increase the counter value,
and format the tweet to print to the screen.
.. code:: ipython3
class TweetListener(tweepy.StreamListener):
def on_data(self, data):
global counter
counter += 1
# Twitter returns data in JSON format - we need to decode it first
decoded = json.loads(data)
# Also, we convert UTF-8 to ASCII ignoring all bad characters sent by users
print('@%s: %s\n' % (decoded['user']['screen_name'], decoded['text'].encode('ascii', 'ignore')))
return True
def on_error(self, status):
print(status)
The tweepy library manages formatting our credentials for the API
request:
.. code:: ipython3
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
Finally we create the object that will parse the twitter stream, and
start it within its own thread.
.. code:: ipython3
stream = tweepy.Stream(auth, TweetListener())
t = threading.Thread(target=stream.filter, kwargs={'track':['ISDC', 'PySD', 'ISDC15', 'Trump']})
t.daemon = True
t.start()
Animation
^^^^^^^^^
First we create a function that will be called at every step in the
integration:
.. code:: ipython3
#make the animation
def animate(t):
global counter
#run the simulation forward
time = model.components.t+dt
model.run({'tweeting':counter},
return_timestamps=time,
return_columns=['tweeting', 'posts_on_timeline'],
initial_condition='current',
collect=True)
out = model.get_record()
ax.plot(out['tweeting'], 'r', label='Tweeting')
ax.plot(out['posts_on_timeline'], 'b', label='Posts on Timeline')
counter = 0
.. parsed-literal::
@alisonjpotter: RT @queenfeminist: Retweet for Bernie Sanders fav for Hillary Clinton
Ignore and Donald Trump wins
@MrTommyCampbell: RT @swhammerhead: #WhenTrumpIsElected the letter H will be removed from the American lexicon as Trump doesn't pronounce it anyways. It wil
@JBRichard50: RT @BradThor: "It's impossible for Perry to have stayed gov of TX for so long if he really is the person we saw in those debates." http://t
@AdeboyeOriade: RT @politicususa: President Obama Rips Donald Trump, Mike Huckabee, and The Entire Republican Party http://t.co/krMZwVV1u0 via @politicusus
@1baldeagle77: The one thing that makes me take Donald Trump seriously as a candidate Rush Limbaugh http://t.co/VxDAyO8xw7 via @voxdotcom
Lastly we set the parameters for the animation, set up the figure, reset
the counter (which has been accumulating posts since we ran the first
part of the code) and start the animation.
.. code:: ipython3
#set the animation parameters
fps=1
seconds=60*30
dt=1./fps
#set up the plot
fig, ax = plt.subplots()
ax.set_xlim(0,seconds)
title = ax.set_title('Expected Twitter Messages on First Page of Feed')
ax.set_xlabel('Seconds')
ax.set_ylabel('Posts, Posts/second')
#reset the counter to start fresh.
counter=0
# call the animator.
animation.FuncAnimation(fig, animate, repeat=False,
frames=seconds*fps, interval=1000./fps,
blit=False)
.. parsed-literal::
@shehelby: RT @ProBirdRights: How can they say me a bird can not be run for Presindent when Donal Trump a giant talking corn can??? #birb2016
@LacrosseUpdate: Hope Hicks flies quietly in the eye of the Trump storm http://t.co/SSUZKcyyiG http://t.co/3MlnhhsEwc
@thedancingqueer: RT @queenfeminist: Retweet for Bernie Sanders fav for Hillary Clinton
Ignore and Donald Trump wins
@BuzzFeedAndrew: "Never a Bush fan," Donald Trump campaigned for H.W. in 1988 held a fundraiser for Jeb in 2002. http://t.co/7S2u6eSyrN
@david_alman: Fucking leftist media spends so much time covering Donald Trump's statements from 20 years ago that it neglects like...anything relevant.
@kcasa7131: RT @pdacosta: #WhenTrumpIsElected, he might appoint himself as Chairman of the Federal Reserve, and begin to issue Trump dollars. http://t.
@presidentrumped: President Trump: Mr Trump is a Gemini this means he is TOTALLY unpredictable! http://t.co/tP5lraAyUH
@MicheleUpdate: Nicolle Wallace: Trump Is 'Doing One Thing Really, Really Well' http://t.co/kLfGNkCqyh
@jjyorktown: RT @ConanOBrien: Im on vacation. Please keep Trump popular while Im gone, I need him in the debates.
@MisaelDiazMLM: .@amazonmex @jcgs68 @amazon Amazon: Dejen de vender los libros de Donald Trump! - Firm la Peti... https://t.co/UMSTq5AxY2 va @Change_M
@StrongerForce: RT @BradThor: "It's impossible for Perry to have stayed gov of TX for so long if he really is the person we saw in those debates." http://t
@cheyannebiancab: RT @bigmacher: #WhenTrumpIsElected everyone will get a Trump action figure that will buy all your play houses & then goes bankrupt. http://
@BigEers: RT @Mediaite: Chris Christie Will No Longer Comment Publicly on Donald Trump http://t.co/UrfQEfGklZ (AUDIO) http://t.co/5fEw69cvM7
@_miramira93: RT @SockHimBopHer: Bill Cosby's legacy is dead.. Donald Trump can possibly be the president.. The Klan is traveling like an AAU team.. And
@paigekathstev: RT @ConanOBrien: Im on vacation. Please keep Trump popular while Im gone, I need him in the debates.
@BMLewis2: RT @GStuedler: I cant see it happening, but in the slim chance it doesa Donald Trump nomination would mean they have completely given up.
@DebndanfarrDeb: Donald Trump Surges to Lead in NH GOP Presidential Poll, Erases Another's Iowa Lead - The Political Insider http://t.co/3exB1TrjPJ via
.. parsed-literal::