Last active
October 2, 2020 22:13
-
-
Save invisiblefunnel/6015e65684325281e65fa9339a78229b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import matplotlib.pyplot as plt\n", | |
"import numpy as np\n", | |
"import partridge as ptg\n", | |
"import scipy.stats" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"inpath = \"/Users/drw/Downloads/SFMTA-2020-09-04.zip\"" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>route_id</th>\n", | |
" <th>service_id</th>\n", | |
" <th>trip_id</th>\n", | |
" <th>trip_headsign</th>\n", | |
" <th>direction_id</th>\n", | |
" <th>block_id</th>\n", | |
" <th>shape_id</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>15761</td>\n", | |
" <td>1</td>\n", | |
" <td>9413147</td>\n", | |
" <td>Presidio Avenue</td>\n", | |
" <td>0</td>\n", | |
" <td>123</td>\n", | |
" <td>179928</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>15761</td>\n", | |
" <td>1</td>\n", | |
" <td>9413148</td>\n", | |
" <td>Presidio Avenue</td>\n", | |
" <td>0</td>\n", | |
" <td>121</td>\n", | |
" <td>179928</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>15761</td>\n", | |
" <td>1</td>\n", | |
" <td>9413149</td>\n", | |
" <td>Presidio Avenue</td>\n", | |
" <td>0</td>\n", | |
" <td>119</td>\n", | |
" <td>179928</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>15761</td>\n", | |
" <td>1</td>\n", | |
" <td>9413150</td>\n", | |
" <td>Presidio Avenue</td>\n", | |
" <td>0</td>\n", | |
" <td>130</td>\n", | |
" <td>179928</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>15761</td>\n", | |
" <td>1</td>\n", | |
" <td>9413151</td>\n", | |
" <td>Presidio Avenue</td>\n", | |
" <td>0</td>\n", | |
" <td>128</td>\n", | |
" <td>179928</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" route_id service_id trip_id trip_headsign direction_id block_id \\\n", | |
"0 15761 1 9413147 Presidio Avenue 0 123 \n", | |
"1 15761 1 9413148 Presidio Avenue 0 121 \n", | |
"2 15761 1 9413149 Presidio Avenue 0 119 \n", | |
"3 15761 1 9413150 Presidio Avenue 0 130 \n", | |
"4 15761 1 9413151 Presidio Avenue 0 128 \n", | |
"\n", | |
" shape_id \n", | |
"0 179928 \n", | |
"1 179928 \n", | |
"2 179928 \n", | |
"3 179928 \n", | |
"4 179928 " | |
] | |
}, | |
"execution_count": 3, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"view = {\"trips.txt\": {}}\n", | |
"\n", | |
"# Choose a date\n", | |
"view[\"trips.txt\"][\"service_id\"] = ptg.read_busiest_date(inpath)[1]\n", | |
"\n", | |
"# Choose a route\n", | |
"view[\"trips.txt\"][\"route_id\"] = ptg.load_feed(inpath, view).routes.route_id[0]\n", | |
"\n", | |
"# Choose a direction\n", | |
"view[\"trips.txt\"][\"direction_id\"] = ptg.load_feed(inpath, view).trips.direction_id[0]\n", | |
"\n", | |
"# Build a working feed\n", | |
"feed = ptg.load_feed(inpath, view)\n", | |
"\n", | |
"feed.trips.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<style scoped>\n", | |
" .dataframe tbody tr th:only-of-type {\n", | |
" vertical-align: middle;\n", | |
" }\n", | |
"\n", | |
" .dataframe tbody tr th {\n", | |
" vertical-align: top;\n", | |
" }\n", | |
"\n", | |
" .dataframe thead th {\n", | |
" text-align: right;\n", | |
" }\n", | |
"</style>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>stop_id</th>\n", | |
" <th>stop_code</th>\n", | |
" <th>stop_name</th>\n", | |
" <th>stop_desc</th>\n", | |
" <th>stop_lat</th>\n", | |
" <th>stop_lon</th>\n", | |
" <th>zone_id</th>\n", | |
" <th>stop_url</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>23</th>\n", | |
" <td>4277</td>\n", | |
" <td>14277</td>\n", | |
" <td>Geary Blvd & 33rd Ave</td>\n", | |
" <td></td>\n", | |
" <td>37.779735</td>\n", | |
" <td>-122.493112</td>\n", | |
" <td></td>\n", | |
" <td></td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" stop_id stop_code stop_name stop_desc stop_lat stop_lon \\\n", | |
"23 4277 14277 Geary Blvd & 33rd Ave 37.779735 -122.493112 \n", | |
"\n", | |
" zone_id stop_url \n", | |
"23 " | |
] | |
}, | |
"execution_count": 4, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Find trips overlapping the time window\n", | |
"trip_ids = feed.stop_times[\n", | |
" (feed.stop_times.arrival_time >= 6*60*60) # 6am\n", | |
" & (feed.stop_times.arrival_time <= 9*60*60) # 9am\n", | |
"].trip_id.unique()\n", | |
"\n", | |
"# Collect the stop_ids for each trip\n", | |
"trip_stops = []\n", | |
"for _, stimes in feed.stop_times[feed.stop_times.trip_id.isin(trip_ids)].groupby(\"trip_id\"):\n", | |
" trip_stops.append(set(stimes.stop_id))\n", | |
"\n", | |
"# Find stop_ids shared between all trips\n", | |
"common_stops = set(trip_stops[0])\n", | |
"for stop_ids in trip_stops[1:]:\n", | |
" common_stops &= stop_ids\n", | |
"\n", | |
"assert common_stops\n", | |
"\n", | |
"# Choose one stop to focus on\n", | |
"subject_stop_id = list(common_stops)[0]\n", | |
"\n", | |
"feed.stops[feed.stops.stop_id==subject_stop_id]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"array([ 8, 8, 8, 8, 8, 3, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,\n", | |
" 8, 8, 8, 8, 8, 9, 9, 8, 10, 8, 8, 8, 8, 8, 8, 4, 5,\n", | |
" 8, 8, 8, 8, 8, 8, 9, 8, 8, 8, 9, 8, 8, 8, 8, 8, 8,\n", | |
" 7, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 5, 3, 5,\n", | |
" 3, 4, 4, 1, 7, 2, 8, 8, 8, 6, 8, 8, 8, 8, 8, 8, 8,\n", | |
" 8, 8, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,\n", | |
" 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 8, 8, 8, 8, 8, 8, 8,\n", | |
" 8, 8, 7, 8, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,\n", | |
" 6, 8, 6, 8])" | |
] | |
}, | |
"execution_count": 5, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"stimes = feed.stop_times[feed.stop_times.stop_id==subject_stop_id].sort_values(\"arrival_time\")\n", | |
"\n", | |
"headway_seconds = stimes.arrival_time[1:].values - stimes.arrival_time[:-1].values\n", | |
"headway_minutes = (headway_seconds / 60.).round().astype(np.int)\n", | |
"\n", | |
"headway_minutes" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"(7.59, 8.0, 8)" | |
] | |
}, | |
"execution_count": 6, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"(\n", | |
" np.mean(headway_minutes).round(2),\n", | |
" np.median(headway_minutes),\n", | |
" scipy.stats.mode(headway_minutes).mode[0]\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"image/png": "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\n", | |
"text/plain": [ | |
"<Figure size 432x288 with 1 Axes>" | |
] | |
}, | |
"metadata": { | |
"needs_background": "light" | |
}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"plt.hist(headway_minutes, bins=10);" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.8.2" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 4 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment