This notebook defines a set of functions that will be exposed by the slack_bot notebook when run. Cells executed in this notebook will be immediately available to Slack users.
To start, we need to make the kernel associated with this ntoebook known to the slack bot notebook. The simplest way to do this is via the local filesystem.
In [1]:
ip = get_ipython()
In [2]:
!rm -f /tmp/defrag_demo
!ln -s {ip.kernel.config['IPKernelApp']['connection_file']} /tmp/defrag_demo
We'll use the IPython auto call feature to avoid the need for parentheses on all invocations. We'll also avoid printing what the call would have been.
In [3]:
%autocall 2
In [4]:
ip.show_rewritten_input = False
Import common libs for convenience.
In [5]:
%matplotlib inline
In [6]:
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import numpy as np
import requests
import json
import datetime
Define a function that prints other functions so users in Slack know what they can say.
In [7]:
def hi():
'''Prints available functions.'''
avail = []
print('Hi there. Try running one of these:\n')
exclude = ('exit', 'quit', 'get_ipython', 'hi')
for key, value in ip.user_ns.items():
if callable(value) and not key.startswith('_') and not key in exclude:
avail.append(key)
print(', '.join(avail))
Now define some demo functions
In [8]:
def plot_random(n=5):
'''Draws N series with N points in each. Just as a demo.'''
data = np.random.rand(n,n)
df = pd.DataFrame(data)
df.plot()
In [9]:
def plot_tips(hue='smoker'):
'''
Plots features of the tip data set as a pair plot colored by one column.
Available columns:
'total_bill', 'tip', 'sex', 'smoker', 'day', 'time', 'size'
'''
tips = sns.load_dataset('tips')
sns.pairplot(tips, hue=hue)
Define functions that use some remote APIs.
In [29]:
_API_KEY = 'XXXXXXXXXXXXXXXXXXXXX'
In [11]:
def _meetups(topic):
r = requests.get("https://api.meetup.com/2/open_events", params={'topic': topic, 'key': _API_KEY})
r.raise_for_status()
results = r.json()['results']
df = pd.DataFrame(results)
df['localtime'] = pd.to_datetime(df.time+df.utc_offset, unit='ms')
return df, results
In [26]:
def bluemix_meetups(limit=10):
'''
Show upcoming Bluemix meetups in a list.
'''
df, results = _meetups('bluemix')
msgs = []
for i, result in enumerate(results[:limit]):
tmpl = '{}. <{result[event_url]}|{result[name]}>'
if 'venue' in result:
tmpl += ' at <https://www.google.com/maps/@{result[venue][lat]},{result[venue][lon]},17z|{result[venue][city]}, {result[venue][country]}>'
tmpl += ' ({result[yes_rsvp_count]} :bust_in_silhouette:)'
msgs.append(tmpl.format(i+1, result=result))
print('Here are the next {} upcoming Bluemix meetups around the world:'.format(limit))
print('\n'.join(msgs))
In [13]:
def bluemix_rsvps(pattern=None):
'''
Show affirmative RSVP growth for the Bluemix meetup over time.
'''
df, _ = _meetups('bluemix')
if pattern is not None:
# sublime/atom-like matching
regex = ''.join(ch+'.*' for ch in pattern)
df = df[df.name.str.contains(regex, case=False)]
if not len(df):
print("Sorry. There are no Bluemix meetup names matching `{}`.".format(pattern))
# take the first if multiple matches
event_id = df.iloc[0]['id']
target_time = pd.to_datetime(df.iloc[0]['time'], unit='ms')
# get rvps without paging (capped at API limit per request)
r = requests.get("https://api.meetup.com/2/rsvps", {'event_id': event_id, 'key': _API_KEY, 'rsvp': 'yes'})
results = r.json()['results']
# convert to datetime
dts = pd.to_datetime([r['created'] for r in results], unit='ms')
events_df = pd.DataFrame(index=dts, columns=['RSVPs'])
# treat every yes as a +1, don't look for users that later changed their mind for now
events_df['RSVPs'] = 1
events_df = events_df.sort().cumsum()
# plot and put a vline at the scheduled datetime of the meetup
ax = events_df.plot(figsize=(10,5))
ax.axvline(x=target_time.to_datetime(), linewidth=2, color='k')
ax.set_ylabel('Yes RSVPs')
ax.set_xlabel('Date/time (UTC)')
ax.set_ylim(top=events_df.tail(1)['RSVPs'].get(0)+5)
ax.set_xlim(right=target_time.to_datetime()+datetime.timedelta(days=2))
_ = ax.set_title(results[0]['event']['name'], y=1.08, loc='center')