Last Friday was anything but your typical Friday. Waking up early to the sweet sounds of raccoons pillaging garbage is never the way to start one’s day. But there I was, lying in bed…thinking about my garbage…first thing in the morning. I begrudgingly got up, walked down the stairs and over a present that my cat decided to leave me during the middle of the night. I opened the front door and to my surprise, everything was still in tact! What a relief. I got lucky there, but school drop-offs were next, and if history is any indicator, this could be anything but smooth.
Three quarters of the way to school drop-off I realized had left my mobile at home on my bedside table.
‘Probably a good thing,’ I thought to myself. ‘They do say it is good to disconnect from the notification bliss we receive every now and then. Plus it’ll reduce my app usage stats, and according to Apple that can only be a good thing. However, I do love listening to music while I walk around…maybe i’ll go back and get it.’
After I dropped off the kids, I went back to the house, grabbed my phone and laptop and then strolled down the Danforth pondering what to do with my day. I walked past a nice local coffee shop called Red Rocket Coffee.
I really like this place and have been here a few times before. I will most definitely hack from this coffee shop today. So, I ordered a flat white and a cookie and then settled down to explore the wonderful world of python.
It wasn’t long before I figured out how to extract and visualize my ride sharing history on a folium map. I’m not sure why I really decided to do this, but I kind of wanted to know what this data would look like. This was kinda neat! Some people may not necessarily share this info, but it’s interesting to be able to figure out how to visualize multiple routes on a map. I wonder what else I can do?
Feeling pretty proud of the map I made, I decided to go home and observe a new tradition I picked up over the summer while in Spain – the Siesta. With that mid afternoon nap calling my name, I quickly packed up my bags and was halfway out the door when suddenly I realized the long walk home was perhaps a little too long.
‘Maybe I’ll just rent a bike,’ I thought to myself. ‘I could just Google directions to find the nearest one…’
OR…
‘I could build a jupyter notebook leveraging Open Data from the City of Toronto and use python to help me determine which station is the closest!’
So there i was, the proverbial fork in the road. A decision needed to be made.
On one side: There was Google, with all the magical things that it can do.
On the other side: A python rabbit hole potentially so deep, I may need a blue pill just to get out of it.
Ok, the python rabbit hole does sound like fun and I do have some time at the moment, so why not.
The Game Plan
Before I get started, let’s put together a quick game plan for what needs to be done. I’ll need to:
- Import Relevant Libraries
- Import Data from the City’s Bike Share Program (Bike Stations & Availability)
- Determine my current latitude and longitude while at the coffee shop
- Create a function to determine the closest stations by latitude and longitude
- Create a Function that determines bike availability at the closest stations
- Plot myself and the closest stations on a folium map
- Plot route to the closest station with bike availability
- Leave coffee shop and rent the bike!
Ok. The plan is ready. Let’s get started!
Importing Libraries…check!
import pandas as pd import folium from folium import plugins import geopy.distance from datetime import datetime import openrouteservice # Used to get lat / longs in between starting and ending lat / long from openrouteservice import convert
Time to Import this Data
Next up, let’s import a few open datasets from the City of Toronto’s website:
- A json list of Bike Share Stations
- A json list of each Bike Share Station’s status (ie. how many bikes each have available)
Let’s read each json file and store them into a dataframe.
First up – retrieving information about all bike share stations in the City of Toronto
stations = pd.read_json('https://tor.publicbikesystem.net/ube/gbfs/v1/en/station_information', lines=True) # Let's see what we have stations.head()
Let’s now take a look when this data was last updated.
datetime.utcfromtimestamp(1537476761).strftime('%Y-%m-%d %H:%M:%S')
Outputs:
# Great! Looks up to date! '2018-09-20 20:52:41'
Ok. Now let’s parse what is in stations[‘data’] to get at the information and store it into its own dataframe.
station_attr = stations['data'][0]['stations'] station_attr = pd.DataFrame(station_attr) station_attr.head()
Outputs:
This looks great! I can work with this.
Next up: Let’s import a json list of each Bike Share Station’s status
This data will give me information on the number of bikes that are currently available, among other metrics. We’ll repeat the same steps as above.
station_status = pd.read_json('https://tor.publicbikesystem.net/ube/gbfs/v1/en/station_status')
station_status_each = pd.DataFrame(station_status['data']['stations'])
station_status_each.head()
Outputs:
We can also transform the last_reported column into a datetime using:
# Let's create a new column which converts last_reported into a timestamp.
station_status_each['latest_report'] = datetime.utcfromtimestamp(station_status_each['last_reported'][0]).strftime('%Y-%m-%d %H:%M:%S')
Now let’s generate my latitude and longitude coordinates
I’m going to use this data to then calculate the distance between my coordinates and all of the coordinates of each bike share station.
I’ll then find the closest station by taking the minimum distance between my coordinates and the lucky station in my array of distances.
To save some time, I’m going to quickly generate my lat long using the following tutorial on MDN:
https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API
# Now let's store latitudes and longitudes these into the following variables. myLat = 43.6823098050454 myLon = -79.3283423644293 # I'll pass mycoord into a function that will help me find the closest stations to my position. mycoord = [myLat,myLon]
Let’s create a function that will find the closest station to my coordinates
To do this we’ll use geopy.distance and return a list of each station’s distance to my coordinates in kilometers (km). I also need to calculate the shortest distance to determine the closest to myself.
def get_closest_stn(mycoord):
'''
Background: Return a list of the closest stations in order
Args:
mycoord: My lat/ long coordinates
Return
distances_to_all: a sorted list of the closest station
closest_stn: the closest station
'''
distances = []
for index, row in station_attr.iterrows():
#coordinates of the station
slat = row['lat']
slong = row['lon']
# need to pass sgeo into geopy function below
sgeo = (slat,slong)
# additional detail about the station to return
sid = row['station_id']
sname = row['name']
capacity = row['capacity']
rental_method = row['rental_methods']
# Calculate the distance
distance = geopy.distance.vincenty(mycoord, sgeo).km
distances.append([sid, distance, sname, capacity, rental_method, slat, slong])
distances_to_all = distances
# sort all stations by distance to my coord
distances_to_all.sort(key=lambda tup: tup[1])
closest = min(distances, key=lambda x: x[1])
print('Information about the closest station to you:')
print('The closest station to you is station # {}, which is located at the intersection of {}.'.format(closest[0], closest[2]))
print('This station is {} km away from your present location.'.format(round(closest[1],2)))
return distances_to_all, closest
Let’s call the function to see what bikeshare station is closest to me:
distances_to_all, closest_stn = get_closest_stn(mycoord)
Comments