Transit APIs in general

Larger context of transit APIs: 45 Transit APIs: Yahoo Traffic, SMSMyBus and BART | ProgrammableWeb. How about NYC?

BART - API Documentation, Station

get info about stations


In [1]:
%run talktools


BART

Let's look at the documentation for the BART API:

Definitely good to familiarize yourself with the BART website

BART developer's group and interesting data

Also a good idea to use the developer's group: https://groups.google.com/forum/#!forum/bart-developers

fun to look at Ridership Reports | bart.gov too.

BART Map

Optional API key signup

Two options for use of key

Benefits of signing up:

If you sign up for your own key you'll still be able to access the API if it turns into a tragedy of the commons. Plus you'll get a backstage pass to check out pre-release functionality that might just break everything you're working on -- or maybe give you a leg up in the marketplace.


In [2]:
# setting up the API Key

import requests
import urllib
from lxml.etree import fromstring


try:
    # to allow import of a registered key if it exists
    from settings import BART_API_KEY
except:
    BART_API_KEY = "MW9S-E7SL-26DU-VV8V"

Stations

Let's look up data about the BART stations.


In [3]:
# [BART - API Documentation, Station](http://api.bart.gov/docs/stn/stns.aspx)

def stations(key=BART_API_KEY):
    url = "http://api.bart.gov/api/stn.aspx?" +  \
            urllib.urlencode({'key':key,
                              'cmd':'stns'})
    r = requests.get(url)
    return r

# grab the content of the XML document returned by the API
r = stations().content
print r


<?xml version="1.0" encoding="utf-8"?><root><uri><![CDATA[http://api.bart.gov/api/stn.aspx?cmd=stns]]></uri><stations><station><name>12th St. Oakland City Center</name><abbr>12TH</abbr><gtfs_latitude>37.803664</gtfs_latitude><gtfs_longitude>-122.271604</gtfs_longitude><address>1245 Broadway</address><city>Oakland</city><county>alameda</county><state>CA</state><zipcode>94612</zipcode></station><station><name>16th St. Mission</name><abbr>16TH</abbr><gtfs_latitude>37.765062</gtfs_latitude><gtfs_longitude>-122.419694</gtfs_longitude><address>2000 Mission Street</address><city>San Francisco</city><county>sanfrancisco</county><state>CA</state><zipcode>94110</zipcode></station><station><name>19th St. Oakland</name><abbr>19TH</abbr><gtfs_latitude>37.80787</gtfs_latitude><gtfs_longitude>-122.269029</gtfs_longitude><address>1900 Broadway</address><city>Oakland</city><county>alameda</county><state>CA</state><zipcode>94612</zipcode></station><station><name>24th St. Mission</name><abbr>24TH</abbr><gtfs_latitude>37.752254</gtfs_latitude><gtfs_longitude>-122.418466</gtfs_longitude><address>2800 Mission Street</address><city>San Francisco</city><county>sanfrancisco</county><state>CA</state><zipcode>94110</zipcode></station><station><name>Ashby</name><abbr>ASHB</abbr><gtfs_latitude>37.853024</gtfs_latitude><gtfs_longitude>-122.26978</gtfs_longitude><address>3100 Adeline Street</address><city>Berkeley</city><county>alameda</county><state>CA</state><zipcode>94703</zipcode></station><station><name>Balboa Park</name><abbr>BALB</abbr><gtfs_latitude>37.72198087</gtfs_latitude><gtfs_longitude>-122.4474142</gtfs_longitude><address>401 Geneva Avenue</address><city>San Francisco</city><county>sanfrancisco</county><state>CA</state><zipcode>94112</zipcode></station><station><name>Bay Fair</name><abbr>BAYF</abbr><gtfs_latitude>37.697185</gtfs_latitude><gtfs_longitude>-122.126871</gtfs_longitude><address>15242 Hesperian Blvd.</address><city>San Leandro</city><county>alameda</county><state>CA</state><zipcode>94578</zipcode></station><station><name>Castro Valley</name><abbr>CAST</abbr><gtfs_latitude>37.690754</gtfs_latitude><gtfs_longitude>-122.075567</gtfs_longitude><address>3301 Norbridge Dr.</address><city>Castro Valley</city><county>alameda</county><state>CA</state><zipcode>94546</zipcode></station><station><name>Civic Center/UN Plaza</name><abbr>CIVC</abbr><gtfs_latitude>37.779528</gtfs_latitude><gtfs_longitude>-122.413756</gtfs_longitude><address>1150 Market Street</address><city>San Francisco</city><county>sanfrancisco</county><state>CA</state><zipcode>94102</zipcode></station><station><name>Coliseum/Oakland Airport</name><abbr>COLS</abbr><gtfs_latitude>37.754006</gtfs_latitude><gtfs_longitude>-122.197273</gtfs_longitude><address>7200 San Leandro St.</address><city>Oakland</city><county>alameda</county><state>CA</state><zipcode>94621</zipcode></station><station><name>Colma</name><abbr>COLM</abbr><gtfs_latitude>37.684638</gtfs_latitude><gtfs_longitude>-122.466233</gtfs_longitude><address>365 D Street</address><city>Colma</city><county>sanmateo</county><state>CA</state><zipcode>94014</zipcode></station><station><name>Concord</name><abbr>CONC</abbr><gtfs_latitude>37.973737</gtfs_latitude><gtfs_longitude>-122.029095</gtfs_longitude><address>1451 Oakland Avenue</address><city>Concord</city><county>contracosta</county><state>CA</state><zipcode>94520</zipcode></station><station><name>Daly City</name><abbr>DALY</abbr><gtfs_latitude>37.70612055</gtfs_latitude><gtfs_longitude>-122.4690807</gtfs_longitude><address>500 John Daly Blvd.</address><city>Daly City</city><county>sanmateo</county><state>CA</state><zipcode>94014</zipcode></station><station><name>Downtown Berkeley</name><abbr>DBRK</abbr><gtfs_latitude>37.869867</gtfs_latitude><gtfs_longitude>-122.268045</gtfs_longitude><address>2160 Shattuck Avenue</address><city>Berkeley</city><county>alameda</county><state>CA</state><zipcode>94704</zipcode></station><station><name>Dublin/Pleasanton</name><abbr>DUBL</abbr><gtfs_latitude>37.701695</gtfs_latitude><gtfs_longitude>-121.900367</gtfs_longitude><address>5801 Owens Dr.</address><city>Pleasanton</city><county>alameda</county><state>CA</state><zipcode>94588</zipcode></station><station><name>El Cerrito del Norte</name><abbr>DELN</abbr><gtfs_latitude>37.925655</gtfs_latitude><gtfs_longitude>-122.317269</gtfs_longitude><address>6400 Cutting Blvd.</address><city>El Cerrito</city><county>contracosta</county><state>CA</state><zipcode>94530</zipcode></station><station><name>El Cerrito Plaza</name><abbr>PLZA</abbr><gtfs_latitude>37.9030588</gtfs_latitude><gtfs_longitude>-122.2992715</gtfs_longitude><address>6699 Fairmount Avenue</address><city>El Cerrito</city><county>contracosta</county><state>CA</state><zipcode>94530</zipcode></station><station><name>Embarcadero</name><abbr>EMBR</abbr><gtfs_latitude>37.792976</gtfs_latitude><gtfs_longitude>-122.396742</gtfs_longitude><address>298 Market Street</address><city>San Francisco</city><county>sanfrancisco</county><state>CA</state><zipcode>94111</zipcode></station><station><name>Fremont</name><abbr>FRMT</abbr><gtfs_latitude>37.557355</gtfs_latitude><gtfs_longitude>-121.9764</gtfs_longitude><address>2000 BART Way</address><city>Fremont</city><county>alameda</county><state>CA</state><zipcode>94536</zipcode></station><station><name>Fruitvale</name><abbr>FTVL</abbr><gtfs_latitude>37.774963</gtfs_latitude><gtfs_longitude>-122.224274</gtfs_longitude><address>3401 East 12th Street</address><city>Oakland</city><county>alameda</county><state>CA</state><zipcode>94601</zipcode></station><station><name>Glen Park</name><abbr>GLEN</abbr><gtfs_latitude>37.732921</gtfs_latitude><gtfs_longitude>-122.434092</gtfs_longitude><address>2901 Diamond Street</address><city>San Francisco</city><county>sanfrancisco</county><state>CA</state><zipcode>94131</zipcode></station><station><name>Hayward</name><abbr>HAYW</abbr><gtfs_latitude>37.670399</gtfs_latitude><gtfs_longitude>-122.087967</gtfs_longitude><address>699 'B' Street</address><city>Hayward</city><county>alameda</county><state>CA</state><zipcode>94541</zipcode></station><station><name>Lafayette</name><abbr>LAFY</abbr><gtfs_latitude>37.893394</gtfs_latitude><gtfs_longitude>-122.123801</gtfs_longitude><address>3601 Deer Hill Road</address><city>Lafayette</city><county>contracosta</county><state>CA</state><zipcode>94549</zipcode></station><station><name>Lake Merritt</name><abbr>LAKE</abbr><gtfs_latitude>37.797484</gtfs_latitude><gtfs_longitude>-122.265609</gtfs_longitude><address>800 Madison Street</address><city>Oakland</city><county>alameda</county><state>CA</state><zipcode>94607</zipcode></station><station><name>MacArthur</name><abbr>MCAR</abbr><gtfs_latitude>37.828415</gtfs_latitude><gtfs_longitude>-122.267227</gtfs_longitude><address>555 40th Street</address><city>Oakland</city><county>alameda</county><state>CA</state><zipcode>94609</zipcode></station><station><name>Millbrae</name><abbr>MLBR</abbr><gtfs_latitude>37.599787</gtfs_latitude><gtfs_longitude>-122.38666</gtfs_longitude><address>200 North Rollins Road</address><city>Millbrae</city><county>sanmateo</county><state>CA</state><zipcode>94030</zipcode></station><station><name>Montgomery St.</name><abbr>MONT</abbr><gtfs_latitude>37.789256</gtfs_latitude><gtfs_longitude>-122.401407</gtfs_longitude><address>598 Market Street</address><city>San Francisco</city><county>sanfrancisco</county><state>CA</state><zipcode>94104</zipcode></station><station><name>North Berkeley</name><abbr>NBRK</abbr><gtfs_latitude>37.87404</gtfs_latitude><gtfs_longitude>-122.283451</gtfs_longitude><address>1750 Sacramento Street</address><city>Berkeley</city><county>alameda</county><state>CA</state><zipcode>94702</zipcode></station><station><name>North Concord/Martinez</name><abbr>NCON</abbr><gtfs_latitude>38.003275</gtfs_latitude><gtfs_longitude>-122.024597</gtfs_longitude><address>3700 Port Chicago Highway</address><city>Concord</city><county>contracosta</county><state>CA</state><zipcode>94520</zipcode></station><station><name>Orinda</name><abbr>ORIN</abbr><gtfs_latitude>37.87836087</gtfs_latitude><gtfs_longitude>-122.1837911</gtfs_longitude><address>11 Camino Pablo</address><city>Orinda</city><county>contracosta</county><state>CA</state><zipcode>94563</zipcode></station><station><name>Pittsburg/Bay Point</name><abbr>PITT</abbr><gtfs_latitude>38.018914</gtfs_latitude><gtfs_longitude>-121.945154</gtfs_longitude><address>1700 West Leland Road</address><city>Pittsburg</city><county>contracosta</county><state>CA</state><zipcode>94565</zipcode></station><station><name>Pleasant Hill/Contra Costa Centre</name><abbr>PHIL</abbr><gtfs_latitude>37.928403</gtfs_latitude><gtfs_longitude>-122.056013</gtfs_longitude><address>1365 Treat Blvd.</address><city>Walnut Creek</city><county>contracosta</county><state>CA</state><zipcode>94597</zipcode></station><station><name>Powell St.</name><abbr>POWL</abbr><gtfs_latitude>37.784991</gtfs_latitude><gtfs_longitude>-122.406857</gtfs_longitude><address>899 Market Street</address><city>San Francisco</city><county>sanfrancisco</county><state>CA</state><zipcode>94102</zipcode></station><station><name>Richmond</name><abbr>RICH</abbr><gtfs_latitude>37.936887</gtfs_latitude><gtfs_longitude>-122.353165</gtfs_longitude><address>1700 Nevin Avenue</address><city>Richmond</city><county>contracosta</county><state>CA</state><zipcode>94801</zipcode></station><station><name>Rockridge</name><abbr>ROCK</abbr><gtfs_latitude>37.844601</gtfs_latitude><gtfs_longitude>-122.251793</gtfs_longitude><address>5660 College Avenue</address><city>Oakland</city><county>alameda</county><state>CA</state><zipcode>94618</zipcode></station><station><name>San Bruno</name><abbr>SBRN</abbr><gtfs_latitude>37.637753</gtfs_latitude><gtfs_longitude>-122.416038</gtfs_longitude><address>1151 Huntington Avenue</address><city>San Bruno</city><county>sanmateo</county><state>CA</state><zipcode>94066</zipcode></station><station><name>San Francisco Int'l Airport</name><abbr>SFIA</abbr><gtfs_latitude>37.616035</gtfs_latitude><gtfs_longitude>-122.392612</gtfs_longitude><address>International Terminal, Level 3</address><city>San Francisco Int'l Airport</city><county>sanmateo</county><state>CA</state><zipcode>94128</zipcode></station><station><name>San Leandro</name><abbr>SANL</abbr><gtfs_latitude>37.72261921</gtfs_latitude><gtfs_longitude>-122.1613112</gtfs_longitude><address>1401 San Leandro Blvd.</address><city>San Leandro</city><county>alameda</county><state>CA</state><zipcode>94577</zipcode></station><station><name>South Hayward</name><abbr>SHAY</abbr><gtfs_latitude>37.63479954</gtfs_latitude><gtfs_longitude>-122.0575506</gtfs_longitude><address>28601 Dixon Street</address><city>Hayward</city><county>alameda</county><state>CA</state><zipcode>94544</zipcode></station><station><name>South San Francisco</name><abbr>SSAN</abbr><gtfs_latitude>37.664174</gtfs_latitude><gtfs_longitude>-122.444116</gtfs_longitude><address>1333 Mission Road</address><city>South San Francisco</city><county>sanmateo</county><state>CA</state><zipcode>94080</zipcode></station><station><name>Union City</name><abbr>UCTY</abbr><gtfs_latitude>37.591208</gtfs_latitude><gtfs_longitude>-122.017867</gtfs_longitude><address>10 Union Square</address><city>Union City</city><county>alameda</county><state>CA</state><zipcode>94587</zipcode></station><station><name>Walnut Creek</name><abbr>WCRK</abbr><gtfs_latitude>37.905628</gtfs_latitude><gtfs_longitude>-122.067423</gtfs_longitude><address>200 Ygnacio Valley Road</address><city>Walnut Creek</city><county>contracosta</county><state>CA</state><zipcode>94596</zipcode></station><station><name>West Dublin/Pleasanton</name><abbr>WDUB</abbr><gtfs_latitude>37.699759</gtfs_latitude><gtfs_longitude>-121.928099</gtfs_longitude><address>6501 Golden Gate Drive</address><city>Dublin</city><county>alameda</county><state>CA</state><zipcode>94568</zipcode></station><station><name>West Oakland</name><abbr>WOAK</abbr><gtfs_latitude>37.80467476</gtfs_latitude><gtfs_longitude>-122.2945822</gtfs_longitude><address>1451 7th Street</address><city>Oakland</city><county>alameda</county><state>CA</state><zipcode>94607</zipcode></station></stations><message></message></root>

In [4]:
# how many stations?
# parse the XML document to look for number of nodes with stations/station

from lxml import etree

stations = etree.fromstring(r).xpath("stations/station")
len(stations)


Out[4]:
44

In [5]:
# let's make a DataFrame (table) out of the stations data

from pandas import DataFrame
from collections import OrderedDict

def station_to_ordereddict(station):
    return OrderedDict([(child.tag, child.text) for child in station.iterchildren()])

stations_df = DataFrame([station_to_ordereddict(station) for station in stations])
stations_df


Out[5]:
abbr address city county gtfs_latitude gtfs_longitude name state zipcode
0 12TH 1245 Broadway Oakland alameda 37.803664 -122.271604 12th St. Oakland City Center CA 94612
1 16TH 2000 Mission Street San Francisco sanfrancisco 37.765062 -122.419694 16th St. Mission CA 94110
2 19TH 1900 Broadway Oakland alameda 37.80787 -122.269029 19th St. Oakland CA 94612
3 24TH 2800 Mission Street San Francisco sanfrancisco 37.752254 -122.418466 24th St. Mission CA 94110
4 ASHB 3100 Adeline Street Berkeley alameda 37.853024 -122.26978 Ashby CA 94703
5 BALB 401 Geneva Avenue San Francisco sanfrancisco 37.72198087 -122.4474142 Balboa Park CA 94112
6 BAYF 15242 Hesperian Blvd. San Leandro alameda 37.697185 -122.126871 Bay Fair CA 94578
7 CAST 3301 Norbridge Dr. Castro Valley alameda 37.690754 -122.075567 Castro Valley CA 94546
8 CIVC 1150 Market Street San Francisco sanfrancisco 37.779528 -122.413756 Civic Center/UN Plaza CA 94102
9 COLS 7200 San Leandro St. Oakland alameda 37.754006 -122.197273 Coliseum/Oakland Airport CA 94621
10 COLM 365 D Street Colma sanmateo 37.684638 -122.466233 Colma CA 94014
11 CONC 1451 Oakland Avenue Concord contracosta 37.973737 -122.029095 Concord CA 94520
12 DALY 500 John Daly Blvd. Daly City sanmateo 37.70612055 -122.4690807 Daly City CA 94014
13 DBRK 2160 Shattuck Avenue Berkeley alameda 37.869867 -122.268045 Downtown Berkeley CA 94704
14 DUBL 5801 Owens Dr. Pleasanton alameda 37.701695 -121.900367 Dublin/Pleasanton CA 94588
15 DELN 6400 Cutting Blvd. El Cerrito contracosta 37.925655 -122.317269 El Cerrito del Norte CA 94530
16 PLZA 6699 Fairmount Avenue El Cerrito contracosta 37.9030588 -122.2992715 El Cerrito Plaza CA 94530
17 EMBR 298 Market Street San Francisco sanfrancisco 37.792976 -122.396742 Embarcadero CA 94111
18 FRMT 2000 BART Way Fremont alameda 37.557355 -121.9764 Fremont CA 94536
19 FTVL 3401 East 12th Street Oakland alameda 37.774963 -122.224274 Fruitvale CA 94601
20 GLEN 2901 Diamond Street San Francisco sanfrancisco 37.732921 -122.434092 Glen Park CA 94131
21 HAYW 699 'B' Street Hayward alameda 37.670399 -122.087967 Hayward CA 94541
22 LAFY 3601 Deer Hill Road Lafayette contracosta 37.893394 -122.123801 Lafayette CA 94549
23 LAKE 800 Madison Street Oakland alameda 37.797484 -122.265609 Lake Merritt CA 94607
24 MCAR 555 40th Street Oakland alameda 37.828415 -122.267227 MacArthur CA 94609
25 MLBR 200 North Rollins Road Millbrae sanmateo 37.599787 -122.38666 Millbrae CA 94030
26 MONT 598 Market Street San Francisco sanfrancisco 37.789256 -122.401407 Montgomery St. CA 94104
27 NBRK 1750 Sacramento Street Berkeley alameda 37.87404 -122.283451 North Berkeley CA 94702
28 NCON 3700 Port Chicago Highway Concord contracosta 38.003275 -122.024597 North Concord/Martinez CA 94520
29 ORIN 11 Camino Pablo Orinda contracosta 37.87836087 -122.1837911 Orinda CA 94563
30 PITT 1700 West Leland Road Pittsburg contracosta 38.018914 -121.945154 Pittsburg/Bay Point CA 94565
31 PHIL 1365 Treat Blvd. Walnut Creek contracosta 37.928403 -122.056013 Pleasant Hill/Contra Costa Centre CA 94597
32 POWL 899 Market Street San Francisco sanfrancisco 37.784991 -122.406857 Powell St. CA 94102
33 RICH 1700 Nevin Avenue Richmond contracosta 37.936887 -122.353165 Richmond CA 94801
34 ROCK 5660 College Avenue Oakland alameda 37.844601 -122.251793 Rockridge CA 94618
35 SBRN 1151 Huntington Avenue San Bruno sanmateo 37.637753 -122.416038 San Bruno CA 94066
36 SFIA International Terminal, Level 3 San Francisco Int'l Airport sanmateo 37.616035 -122.392612 San Francisco Int'l Airport CA 94128
37 SANL 1401 San Leandro Blvd. San Leandro alameda 37.72261921 -122.1613112 San Leandro CA 94577
38 SHAY 28601 Dixon Street Hayward alameda 37.63479954 -122.0575506 South Hayward CA 94544
39 SSAN 1333 Mission Road South San Francisco sanmateo 37.664174 -122.444116 South San Francisco CA 94080
40 UCTY 10 Union Square Union City alameda 37.591208 -122.017867 Union City CA 94587
41 WCRK 200 Ygnacio Valley Road Walnut Creek contracosta 37.905628 -122.067423 Walnut Creek CA 94596
42 WDUB 6501 Golden Gate Drive Dublin alameda 37.699759 -121.928099 West Dublin/Pleasanton CA 94568
43 WOAK 1451 7th Street Oakland alameda 37.80467476 -122.2945822 West Oakland CA 94607

44 rows × 9 columns

Plotting stations on a Map

Let's use the latitude, longitude information to construct a map of the stations.


In [6]:
for s in stations_df.T.to_dict().values():
    print s['name'], float(s['gtfs_latitude']), float(s['gtfs_longitude'])


12th St. Oakland City Center 37.803664 -122.271604
16th St. Mission 37.765062 -122.419694
19th St. Oakland 37.80787 -122.269029
24th St. Mission 37.752254 -122.418466
Ashby 37.853024 -122.26978
Balboa Park 37.72198087 -122.4474142
Bay Fair 37.697185 -122.126871
Castro Valley 37.690754 -122.075567
Civic Center/UN Plaza 37.779528 -122.413756
Coliseum/Oakland Airport 37.754006 -122.197273
Colma 37.684638 -122.466233
Concord 37.973737 -122.029095
Daly City 37.70612055 -122.4690807
Downtown Berkeley 37.869867 -122.268045
Dublin/Pleasanton 37.701695 -121.900367
El Cerrito del Norte 37.925655 -122.317269
El Cerrito Plaza 37.9030588 -122.2992715
Embarcadero 37.792976 -122.396742
Fremont 37.557355 -121.9764
Fruitvale 37.774963 -122.224274
Glen Park 37.732921 -122.434092
Hayward 37.670399 -122.087967
Lafayette 37.893394 -122.123801
Lake Merritt 37.797484 -122.265609
MacArthur 37.828415 -122.267227
Millbrae 37.599787 -122.38666
Montgomery St. 37.789256 -122.401407
North Berkeley 37.87404 -122.283451
North Concord/Martinez 38.003275 -122.024597
Orinda 37.87836087 -122.1837911
Pittsburg/Bay Point 38.018914 -121.945154
Pleasant Hill/Contra Costa Centre 37.928403 -122.056013
Powell St. 37.784991 -122.406857
Richmond 37.936887 -122.353165
Rockridge 37.844601 -122.251793
San Bruno 37.637753 -122.416038
San Francisco Int'l Airport 37.616035 -122.392612
San Leandro 37.72261921 -122.1613112
South Hayward 37.63479954 -122.0575506
South San Francisco 37.664174 -122.444116
Union City 37.591208 -122.017867
Walnut Creek 37.905628 -122.067423
West Dublin/Pleasanton 37.699759 -121.928099
West Oakland 37.80467476 -122.2945822

In [7]:
# plot the maps using folium 
# possible alternative: leaflet.js widget that Brian Granger working on 
# https://github.com/ellisonbg/leaftletwidget

# http://nbviewer.ipython.org/gist/bburky/7763555/folium-ipython.ipynb

from IPython.display import HTML
import folium

def inline_map(map):
    """
    Embeds the HTML source of the map directly into the IPython notebook.
    
    This method will not work if the map depends on any files (json data). Also this uses
    the HTML5 srcdoc attribute, which may not be supported in all browsers.
    """
    map._build_map()
    return HTML('<iframe srcdoc="{srcdoc}" style="width: 100%; height: 510px; border: none"></iframe>'.format(srcdoc=map.HTML.replace('"', '&quot;')))

def embed_map(map, path="map.html"):
    """
    Embeds a linked iframe to the map into the IPython notebook.
    
    Note: this method will not capture the source of the map into the notebook.
    This method should work for all maps (as long as they use relative urls).
    """
    map.create_map(path=path)
    return HTML('<iframe src="files/{path}" style="width: 100%; height: 510px; border: none"></iframe>'.format(path=path))

In [8]:
bart_map = folium.Map(location=[37.8717, -122.2728], zoom_start=9)


# for airport in islice(airports,None):
#    lat =  float(airport['Origin_lat'])
#    lon = float(airport['Origin_long'])
#    label = str(airport['Origin_airport'])  # don't know why str necessary here
#    airport_map.simple_marker([lat,lon],popup=label)


for s in stations_df.T.to_dict().values():
    bart_map.simple_marker([float(s['gtfs_latitude']), float(s['gtfs_longitude'])],
                           popup=s['name'])
inline_map(bart_map)


Out[8]:

In [9]:
def train_count(key=BART_API_KEY):
    url = "http://api.bart.gov/api/bsa.aspx?" +  \
        urllib.urlencode({'cmd':'count',
                          'key':key})
                                                                  
    r = requests.get(url)
    doc = fromstring(r.content)
    call_dt = doc.find('date').text + " " +doc.find('time').text
    count = doc.find('traincount').text
    return (call_dt, count)

d = train_count()
d


Out[9]:
('05/27/2014 14:45:00 PM PDT', '52')

Real time estimated departure times

One of the most useful parts of the BART API is real-time departure information:


In [10]:
from dateutil.parser import parse
from dateutil.tz import tzlocal
from lxml.etree import fromstring

def etd(orig, key=BART_API_KEY):
    url = "http://api.bart.gov/api/etd.aspx?" +  \
            urllib.urlencode({'cmd':'etd',
                              'orig':orig,
                              'key':key})
                                                                  
    r = requests.get(url)
    doc = fromstring(r.content)
    
    estimations_list = []

    # parse the datetime for the API call

    s = doc.find('date').text + " " +doc.find('time').text
    call_dt = parse(s)
    
    # turn the results into a rectangular format

    # parse the station

    for station in doc.findall('station'):
        etds = station.findall('etd')
        for etd in etds:
            estimates = etd.findall('estimate')
            for estimate in estimates:
                estimate_tuple = [(child.tag, child.text) for child in estimate.iterchildren()]
                
                estimate_tuple += [('call_dt', call_dt),
                                   ('station', station.find('abbr').text),
                                   ('destination', etd.find('abbreviation').text)]
               
                estimations_list.append(dict(estimate_tuple))

    return estimations_list

In [11]:
# we can get ETA for all stations

from pandas import DataFrame
import pandas as pd
import numpy as np

df = DataFrame(etd('all'))
df


Out[11]:
bikeflag call_dt color destination direction hexcolor length minutes platform station
0 1 2014-05-27 14:45:07-07:00 BLUE DALY North #0099cc 8 2 2 LAKE
1 1 2014-05-27 14:45:07-07:00 GREEN DALY North #339933 10 10 2 LAKE
2 1 2014-05-27 14:45:07-07:00 BLUE DALY North #0099cc 8 17 2 LAKE
3 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 7 1 LAKE
4 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 22 1 LAKE
5 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 37 1 LAKE
6 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 8 4 1 LAKE
7 1 2014-05-27 14:45:07-07:00 GREEN FRMT South #339933 4 14 1 LAKE
8 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 8 19 1 LAKE
9 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 3 5 2 LAKE
10 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 3 19 2 LAKE
11 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 6 34 2 LAKE
12 1 2014-05-27 14:45:07-07:00 GREEN DALY North #339933 10 6 2 FTVL
13 1 2014-05-27 14:45:07-07:00 BLUE DALY North #0099cc 8 12 2 FTVL
14 1 2014-05-27 14:45:07-07:00 GREEN DALY North #339933 8 21 2 FTVL
15 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 10 1 FTVL
16 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 26 1 FTVL
17 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 41 1 FTVL
18 1 2014-05-27 14:45:07-07:00 GREEN FRMT South #339933 4 3 1 FTVL
19 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 8 8 1 FTVL
20 1 2014-05-27 14:45:07-07:00 GREEN FRMT South #339933 4 17 1 FTVL
21 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 3 1 2 FTVL
22 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 3 15 2 FTVL
23 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 6 30 2 FTVL
24 1 2014-05-27 14:45:07-07:00 GREEN DALY North #339933 10 3 2 COLS
25 1 2014-05-27 14:45:07-07:00 BLUE DALY North #0099cc 8 9 2 COLS
26 1 2014-05-27 14:45:07-07:00 GREEN DALY North #339933 8 18 2 COLS
27 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 14 1 COLS
28 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 29 1 COLS
29 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 44 1 COLS
30 1 2014-05-27 14:45:07-07:00 GREEN FRMT South #339933 4 7 1 COLS
31 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 8 11 1 COLS
32 1 2014-05-27 14:45:07-07:00 GREEN FRMT South #339933 4 21 1 COLS
33 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 3 12 2 COLS
34 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 6 27 2 COLS
35 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 4 42 2 COLS
36 1 2014-05-27 14:45:07-07:00 BLUE DALY North #0099cc 8 5 2 SANL
37 1 2014-05-27 14:45:07-07:00 GREEN DALY North #339933 8 14 2 SANL
38 1 2014-05-27 14:45:07-07:00 BLUE DALY North #0099cc 8 21 2 SANL
39 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 3 1 SANL
40 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 18 1 SANL
41 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 33 1 SANL
42 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 6 Leaving 1 SANL
43 1 2014-05-27 14:45:07-07:00 GREEN FRMT South #339933 4 11 1 SANL
44 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 8 15 1 SANL
45 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 3 8 2 SANL
46 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 6 23 2 SANL
47 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 4 38 2 SANL
48 1 2014-05-27 14:45:07-07:00 BLUE DALY North #0099cc 8 1 2 BAYF
49 1 2014-05-27 14:45:07-07:00 GREEN DALY North #339933 8 10 2 BAYF
50 1 2014-05-27 14:45:07-07:00 BLUE DALY North #0099cc 8 17 2 BAYF
51 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 6 1 BAYF
52 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 21 1 BAYF
53 1 2014-05-27 14:45:07-07:00 BLUE DUBL South #0099cc 4 37 1 BAYF
54 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 6 4 1 BAYF
55 1 2014-05-27 14:45:07-07:00 GREEN FRMT South #339933 4 14 1 BAYF
56 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 8 19 1 BAYF
57 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 3 4 2 BAYF
58 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 6 19 2 BAYF
59 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 4 34 2 BAYF
... ... ... ... ... ... ... ... ... ...

497 rows × 10 columns


In [12]:
# look up information for El Cerrito Plaza

df[df.station == 'PLZA']


Out[12]:
bikeflag call_dt color destination direction hexcolor length minutes platform station
431 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 6 13 2 PLZA
432 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 6 28 2 PLZA
433 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 6 43 2 PLZA
434 1 2014-05-27 14:45:07-07:00 RED MLBR South #ff0000 5 5 2 PLZA
435 1 2014-05-27 14:45:07-07:00 RED MLBR South #ff0000 9 20 2 PLZA
436 1 2014-05-27 14:45:07-07:00 RED MLBR South #ff0000 9 35 2 PLZA
437 1 2014-05-27 14:45:07-07:00 RED RICH North #ff0000 5 1 1 PLZA
438 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 3 11 1 PLZA
439 1 2014-05-27 14:45:07-07:00 RED RICH North #ff0000 5 17 1 PLZA

9 rows × 10 columns

Use someone else's BART API library

  • Now that we have some feel for the BART API, we now decide between:

    • implementing more of the API ourselves in Python
    • use someone else's library (if such libraries exist.)

In the case of the BART API, there is: https://pypi.python.org/pypi/bart_api/0.1 (github) by Reuben Castelino

Easiest way to use the library is to use pip from PyPi. Should be able to do:

pip install bart_api

but as of 2014.05.25, the version doesn't work for Python 2.x. The github version is more up-to-date. You can do installation from github (https://github.com/projectdelphai/bart_api):

pip install git+git://github.com/projectdelphai/bart_api.git

I've made some changes so it might be helpful to use my fork until my changes get folded back into the main project:

 pip install git+git://github.com/rdhyee/bart_api.git

In [13]:
# example:  use the bart_api to calculate the number of active trains

import bart_api 
reload(bart_api)

bart = bart_api.BartApi()
bart.number_of_trains()


Out[13]:
'52'

In [14]:
# stations

station_list = bart.get_stations()
station_list


Out[14]:
[{'abbr': '12TH',
  'address': '1245 Broadway',
  'city': 'Oakland',
  'county': 'alameda',
  'gtfs_latitude': '37.803664',
  'gtfs_longitude': '-122.271604',
  'name': '12th St. Oakland City Center',
  'state': 'CA',
  'zipcode': '94612'},
 {'abbr': '16TH',
  'address': '2000 Mission Street',
  'city': 'San Francisco',
  'county': 'sanfrancisco',
  'gtfs_latitude': '37.765062',
  'gtfs_longitude': '-122.419694',
  'name': '16th St. Mission',
  'state': 'CA',
  'zipcode': '94110'},
 {'abbr': '19TH',
  'address': '1900 Broadway',
  'city': 'Oakland',
  'county': 'alameda',
  'gtfs_latitude': '37.80787',
  'gtfs_longitude': '-122.269029',
  'name': '19th St. Oakland',
  'state': 'CA',
  'zipcode': '94612'},
 {'abbr': '24TH',
  'address': '2800 Mission Street',
  'city': 'San Francisco',
  'county': 'sanfrancisco',
  'gtfs_latitude': '37.752254',
  'gtfs_longitude': '-122.418466',
  'name': '24th St. Mission',
  'state': 'CA',
  'zipcode': '94110'},
 {'abbr': 'ASHB',
  'address': '3100 Adeline Street',
  'city': 'Berkeley',
  'county': 'alameda',
  'gtfs_latitude': '37.853024',
  'gtfs_longitude': '-122.26978',
  'name': 'Ashby',
  'state': 'CA',
  'zipcode': '94703'},
 {'abbr': 'BALB',
  'address': '401 Geneva Avenue',
  'city': 'San Francisco',
  'county': 'sanfrancisco',
  'gtfs_latitude': '37.72198087',
  'gtfs_longitude': '-122.4474142',
  'name': 'Balboa Park',
  'state': 'CA',
  'zipcode': '94112'},
 {'abbr': 'BAYF',
  'address': '15242 Hesperian Blvd.',
  'city': 'San Leandro',
  'county': 'alameda',
  'gtfs_latitude': '37.697185',
  'gtfs_longitude': '-122.126871',
  'name': 'Bay Fair',
  'state': 'CA',
  'zipcode': '94578'},
 {'abbr': 'CAST',
  'address': '3301 Norbridge Dr.',
  'city': 'Castro Valley',
  'county': 'alameda',
  'gtfs_latitude': '37.690754',
  'gtfs_longitude': '-122.075567',
  'name': 'Castro Valley',
  'state': 'CA',
  'zipcode': '94546'},
 {'abbr': 'CIVC',
  'address': '1150 Market Street',
  'city': 'San Francisco',
  'county': 'sanfrancisco',
  'gtfs_latitude': '37.779528',
  'gtfs_longitude': '-122.413756',
  'name': 'Civic Center/UN Plaza',
  'state': 'CA',
  'zipcode': '94102'},
 {'abbr': 'COLS',
  'address': '7200 San Leandro St.',
  'city': 'Oakland',
  'county': 'alameda',
  'gtfs_latitude': '37.754006',
  'gtfs_longitude': '-122.197273',
  'name': 'Coliseum/Oakland Airport',
  'state': 'CA',
  'zipcode': '94621'},
 {'abbr': 'COLM',
  'address': '365 D Street',
  'city': 'Colma',
  'county': 'sanmateo',
  'gtfs_latitude': '37.684638',
  'gtfs_longitude': '-122.466233',
  'name': 'Colma',
  'state': 'CA',
  'zipcode': '94014'},
 {'abbr': 'CONC',
  'address': '1451 Oakland Avenue',
  'city': 'Concord',
  'county': 'contracosta',
  'gtfs_latitude': '37.973737',
  'gtfs_longitude': '-122.029095',
  'name': 'Concord',
  'state': 'CA',
  'zipcode': '94520'},
 {'abbr': 'DALY',
  'address': '500 John Daly Blvd.',
  'city': 'Daly City',
  'county': 'sanmateo',
  'gtfs_latitude': '37.70612055',
  'gtfs_longitude': '-122.4690807',
  'name': 'Daly City',
  'state': 'CA',
  'zipcode': '94014'},
 {'abbr': 'DBRK',
  'address': '2160 Shattuck Avenue',
  'city': 'Berkeley',
  'county': 'alameda',
  'gtfs_latitude': '37.869867',
  'gtfs_longitude': '-122.268045',
  'name': 'Downtown Berkeley',
  'state': 'CA',
  'zipcode': '94704'},
 {'abbr': 'DUBL',
  'address': '5801 Owens Dr.',
  'city': 'Pleasanton',
  'county': 'alameda',
  'gtfs_latitude': '37.701695',
  'gtfs_longitude': '-121.900367',
  'name': 'Dublin/Pleasanton',
  'state': 'CA',
  'zipcode': '94588'},
 {'abbr': 'DELN',
  'address': '6400 Cutting Blvd.',
  'city': 'El Cerrito',
  'county': 'contracosta',
  'gtfs_latitude': '37.925655',
  'gtfs_longitude': '-122.317269',
  'name': 'El Cerrito del Norte',
  'state': 'CA',
  'zipcode': '94530'},
 {'abbr': 'PLZA',
  'address': '6699 Fairmount Avenue',
  'city': 'El Cerrito',
  'county': 'contracosta',
  'gtfs_latitude': '37.9030588',
  'gtfs_longitude': '-122.2992715',
  'name': 'El Cerrito Plaza',
  'state': 'CA',
  'zipcode': '94530'},
 {'abbr': 'EMBR',
  'address': '298 Market Street',
  'city': 'San Francisco',
  'county': 'sanfrancisco',
  'gtfs_latitude': '37.792976',
  'gtfs_longitude': '-122.396742',
  'name': 'Embarcadero',
  'state': 'CA',
  'zipcode': '94111'},
 {'abbr': 'FRMT',
  'address': '2000 BART Way',
  'city': 'Fremont',
  'county': 'alameda',
  'gtfs_latitude': '37.557355',
  'gtfs_longitude': '-121.9764',
  'name': 'Fremont',
  'state': 'CA',
  'zipcode': '94536'},
 {'abbr': 'FTVL',
  'address': '3401 East 12th Street',
  'city': 'Oakland',
  'county': 'alameda',
  'gtfs_latitude': '37.774963',
  'gtfs_longitude': '-122.224274',
  'name': 'Fruitvale',
  'state': 'CA',
  'zipcode': '94601'},
 {'abbr': 'GLEN',
  'address': '2901 Diamond Street',
  'city': 'San Francisco',
  'county': 'sanfrancisco',
  'gtfs_latitude': '37.732921',
  'gtfs_longitude': '-122.434092',
  'name': 'Glen Park',
  'state': 'CA',
  'zipcode': '94131'},
 {'abbr': 'HAYW',
  'address': "699 'B' Street",
  'city': 'Hayward',
  'county': 'alameda',
  'gtfs_latitude': '37.670399',
  'gtfs_longitude': '-122.087967',
  'name': 'Hayward',
  'state': 'CA',
  'zipcode': '94541'},
 {'abbr': 'LAFY',
  'address': '3601 Deer Hill Road',
  'city': 'Lafayette',
  'county': 'contracosta',
  'gtfs_latitude': '37.893394',
  'gtfs_longitude': '-122.123801',
  'name': 'Lafayette',
  'state': 'CA',
  'zipcode': '94549'},
 {'abbr': 'LAKE',
  'address': '800 Madison Street',
  'city': 'Oakland',
  'county': 'alameda',
  'gtfs_latitude': '37.797484',
  'gtfs_longitude': '-122.265609',
  'name': 'Lake Merritt',
  'state': 'CA',
  'zipcode': '94607'},
 {'abbr': 'MCAR',
  'address': '555 40th Street',
  'city': 'Oakland',
  'county': 'alameda',
  'gtfs_latitude': '37.828415',
  'gtfs_longitude': '-122.267227',
  'name': 'MacArthur',
  'state': 'CA',
  'zipcode': '94609'},
 {'abbr': 'MLBR',
  'address': '200 North Rollins Road',
  'city': 'Millbrae',
  'county': 'sanmateo',
  'gtfs_latitude': '37.599787',
  'gtfs_longitude': '-122.38666',
  'name': 'Millbrae',
  'state': 'CA',
  'zipcode': '94030'},
 {'abbr': 'MONT',
  'address': '598 Market Street',
  'city': 'San Francisco',
  'county': 'sanfrancisco',
  'gtfs_latitude': '37.789256',
  'gtfs_longitude': '-122.401407',
  'name': 'Montgomery St.',
  'state': 'CA',
  'zipcode': '94104'},
 {'abbr': 'NBRK',
  'address': '1750 Sacramento Street',
  'city': 'Berkeley',
  'county': 'alameda',
  'gtfs_latitude': '37.87404',
  'gtfs_longitude': '-122.283451',
  'name': 'North Berkeley',
  'state': 'CA',
  'zipcode': '94702'},
 {'abbr': 'NCON',
  'address': '3700 Port Chicago Highway',
  'city': 'Concord',
  'county': 'contracosta',
  'gtfs_latitude': '38.003275',
  'gtfs_longitude': '-122.024597',
  'name': 'North Concord/Martinez',
  'state': 'CA',
  'zipcode': '94520'},
 {'abbr': 'ORIN',
  'address': '11 Camino Pablo',
  'city': 'Orinda',
  'county': 'contracosta',
  'gtfs_latitude': '37.87836087',
  'gtfs_longitude': '-122.1837911',
  'name': 'Orinda',
  'state': 'CA',
  'zipcode': '94563'},
 {'abbr': 'PITT',
  'address': '1700 West Leland Road',
  'city': 'Pittsburg',
  'county': 'contracosta',
  'gtfs_latitude': '38.018914',
  'gtfs_longitude': '-121.945154',
  'name': 'Pittsburg/Bay Point',
  'state': 'CA',
  'zipcode': '94565'},
 {'abbr': 'PHIL',
  'address': '1365 Treat Blvd.',
  'city': 'Walnut Creek',
  'county': 'contracosta',
  'gtfs_latitude': '37.928403',
  'gtfs_longitude': '-122.056013',
  'name': 'Pleasant Hill/Contra Costa Centre',
  'state': 'CA',
  'zipcode': '94597'},
 {'abbr': 'POWL',
  'address': '899 Market Street',
  'city': 'San Francisco',
  'county': 'sanfrancisco',
  'gtfs_latitude': '37.784991',
  'gtfs_longitude': '-122.406857',
  'name': 'Powell St.',
  'state': 'CA',
  'zipcode': '94102'},
 {'abbr': 'RICH',
  'address': '1700 Nevin Avenue',
  'city': 'Richmond',
  'county': 'contracosta',
  'gtfs_latitude': '37.936887',
  'gtfs_longitude': '-122.353165',
  'name': 'Richmond',
  'state': 'CA',
  'zipcode': '94801'},
 {'abbr': 'ROCK',
  'address': '5660 College Avenue',
  'city': 'Oakland',
  'county': 'alameda',
  'gtfs_latitude': '37.844601',
  'gtfs_longitude': '-122.251793',
  'name': 'Rockridge',
  'state': 'CA',
  'zipcode': '94618'},
 {'abbr': 'SBRN',
  'address': '1151 Huntington Avenue',
  'city': 'San Bruno',
  'county': 'sanmateo',
  'gtfs_latitude': '37.637753',
  'gtfs_longitude': '-122.416038',
  'name': 'San Bruno',
  'state': 'CA',
  'zipcode': '94066'},
 {'abbr': 'SFIA',
  'address': 'International Terminal, Level 3',
  'city': "San Francisco Int'l Airport",
  'county': 'sanmateo',
  'gtfs_latitude': '37.616035',
  'gtfs_longitude': '-122.392612',
  'name': "San Francisco Int'l Airport",
  'state': 'CA',
  'zipcode': '94128'},
 {'abbr': 'SANL',
  'address': '1401 San Leandro Blvd.',
  'city': 'San Leandro',
  'county': 'alameda',
  'gtfs_latitude': '37.72261921',
  'gtfs_longitude': '-122.1613112',
  'name': 'San Leandro',
  'state': 'CA',
  'zipcode': '94577'},
 {'abbr': 'SHAY',
  'address': '28601 Dixon Street',
  'city': 'Hayward',
  'county': 'alameda',
  'gtfs_latitude': '37.63479954',
  'gtfs_longitude': '-122.0575506',
  'name': 'South Hayward',
  'state': 'CA',
  'zipcode': '94544'},
 {'abbr': 'SSAN',
  'address': '1333 Mission Road',
  'city': 'South San Francisco',
  'county': 'sanmateo',
  'gtfs_latitude': '37.664174',
  'gtfs_longitude': '-122.444116',
  'name': 'South San Francisco',
  'state': 'CA',
  'zipcode': '94080'},
 {'abbr': 'UCTY',
  'address': '10 Union Square',
  'city': 'Union City',
  'county': 'alameda',
  'gtfs_latitude': '37.591208',
  'gtfs_longitude': '-122.017867',
  'name': 'Union City',
  'state': 'CA',
  'zipcode': '94587'},
 {'abbr': 'WCRK',
  'address': '200 Ygnacio Valley Road',
  'city': 'Walnut Creek',
  'county': 'contracosta',
  'gtfs_latitude': '37.905628',
  'gtfs_longitude': '-122.067423',
  'name': 'Walnut Creek',
  'state': 'CA',
  'zipcode': '94596'},
 {'abbr': 'WDUB',
  'address': '6501 Golden Gate Drive',
  'city': 'Dublin',
  'county': 'alameda',
  'gtfs_latitude': '37.699759',
  'gtfs_longitude': '-121.928099',
  'name': 'West Dublin/Pleasanton',
  'state': 'CA',
  'zipcode': '94568'},
 {'abbr': 'WOAK',
  'address': '1451 7th Street',
  'city': 'Oakland',
  'county': 'alameda',
  'gtfs_latitude': '37.80467476',
  'gtfs_longitude': '-122.2945822',
  'name': 'West Oakland',
  'state': 'CA',
  'zipcode': '94607'}]

In [15]:
#routes = bart.routes(sched, date)
# http://api.bart.gov/docs/route/routes.aspx
# http://api.bart.gov/api/route.aspx?cmd=routes&key=MW9S-E7SL-26DU-VV8V

routes = bart.routes(34, '05/27/2014')
routes


Out[15]:
[{'abbr': 'PITT-SFIA',
  'color': '#ffff33',
  'name': 'Pittsburg/Bay Point - SFIA/Millbrae',
  'number': '1',
  'routeID': 'ROUTE 1'},
 {'abbr': 'DALY-DUBL',
  'color': '#0099cc',
  'name': 'Daly City - Dublin/Pleasanton',
  'number': '12',
  'routeID': 'ROUTE 12'},
 {'abbr': 'DALY-FRMT',
  'color': '#339933',
  'name': 'Daly City - Fremont',
  'number': '6',
  'routeID': 'ROUTE 6'},
 {'abbr': 'DUBL-DALY',
  'color': '#0099cc',
  'name': 'Dublin/Pleasanton - Daly City',
  'number': '11',
  'routeID': 'ROUTE 11'},
 {'abbr': 'FRMT-DALY',
  'color': '#339933',
  'name': 'Fremont - Daly City',
  'number': '5',
  'routeID': 'ROUTE 5'},
 {'abbr': 'FRMT-RICH',
  'color': '#ff9933',
  'name': 'Fremont - Richmond',
  'number': '3',
  'routeID': 'ROUTE 3'},
 {'abbr': 'MLBR-RICH',
  'color': '#ff0000',
  'name': 'Millbrae/Daly City - Richmond',
  'number': '8',
  'routeID': 'ROUTE 8'},
 {'abbr': 'RICH-FRMT',
  'color': '#ff9933',
  'name': 'Richmond - Fremont',
  'number': '4',
  'routeID': 'ROUTE 4'},
 {'abbr': 'RICH-MLBR',
  'color': '#ff0000',
  'name': 'Richmond - Daly City/Millbrae',
  'number': '7',
  'routeID': 'ROUTE 7'},
 {'abbr': 'SFIA-PITT',
  'color': '#ffff33',
  'name': 'Millbrae/SFIA - Pittsburg/Bay Point',
  'number': '2',
  'routeID': 'ROUTE 2'}]

In [16]:
# let's display the routes with the BART color coding
# sorted by BART numbering
# nice feature of the IPython notebook to able to use HTML

from IPython.display import HTML
import jinja2


ROUTE_TEMPLATE = """
<div class="wrap">
<table>
 {% for item in items %}<tr>
 <td style="background-color:{{item.color}}">{{item.name}}</td>
 <td>{{item.number}}</td>
 </tr>
 {% endfor %}
</table>
</div>
"""

template = jinja2.Template(ROUTE_TEMPLATE)

HTML(template.render(items=sorted(routes, key=lambda r: int(r.get('number')))))


Out[16]:
Pittsburg/Bay Point - SFIA/Millbrae 1
Millbrae/SFIA - Pittsburg/Bay Point 2
Fremont - Richmond 3
Richmond - Fremont 4
Fremont - Daly City 5
Daly City - Fremont 6
Richmond - Daly City/Millbrae 7
Millbrae/Daly City - Richmond 8
Dublin/Pleasanton - Daly City 11
Daly City - Dublin/Pleasanton 12

Pros and Cons of Writing your own library vs using someone else's

  • a chance to collaborate and improve on what's already there vs doing something different
  • sometime it takes a fair amount of work to understand other people's code. (of course, sometimes hard to read one's own code!)

In [17]:
# bart.get_route_schedule seems to be outdated
# https://github.com/projectdelphai/bart_api/blob/5101e0deec452ddca2f76d0d6d97d6725080ae31/bart_api/__init__.py#L147


bart.get_route_schedule('4')


Out[17]:
{}

In [18]:
# http://api.bart.gov/docs/sched/routesched.aspx
# The optional "date" and "sched" parameters should not be used together. 
# If they are, the date will be ignored, and the sched parameter will be used.

# to get route 4 (Richmond->Fremont)
# http://api.bart.gov/api/sched.aspx?cmd=routesched&route=4&key=MW9S-E7SL-26DU-VV8V

def filter_none(d):
    return dict([(k,v) for (k,v) in d.items() if v is not None])

def route_schedule(route, sched=None, date=None, l=0, key=BART_API_KEY):
    url = "http://api.bart.gov/api/sched.aspx?" +  \
        urllib.urlencode(filter_none({'cmd':'routesched',
                          'route':route,
                          'sched':sched,
                          'date':date,
                          'l':l,
                          'key':key}))
                                                                  
    r = requests.get(url)
    doc = fromstring(r.content)
    return doc

doc = route_schedule(4)
doc


Out[18]:
<Element root at 0x106e8d0e0>

In [19]:
print doc.find("date").text, "\n"

for train in doc.findall('route/train'):
    print train.attrib['index']
    for stop in train.iterchildren():
        print stop.attrib['station'], stop.attrib['origTime']
    print


5/27/2014 

1
RICH 4:20 AM
DELN 4:24 AM
PLZA 4:27 AM
NBRK 4:30 AM
DBRK 4:33 AM
ASHB 4:35 AM
MCAR 4:38 AM
19TH 4:44 AM
12TH 4:45 AM
LAKE 4:48 AM
FTVL 4:52 AM
COLS 4:55 AM
SANL 4:59 AM
BAYF 5:03 AM
HAYW 5:07 AM
SHAY 5:11 AM
UCTY 5:16 AM
FRMT 5:21 AM

2
RICH 4:35 AM
DELN 4:39 AM
PLZA 4:42 AM
NBRK 4:45 AM
DBRK 4:48 AM
ASHB 4:50 AM
MCAR 4:53 AM
19TH 4:59 AM
12TH 5:00 AM
LAKE 5:03 AM
FTVL 5:07 AM
COLS 5:10 AM
SANL 5:14 AM
BAYF 5:18 AM
HAYW 5:22 AM
SHAY 5:26 AM
UCTY 5:31 AM
FRMT 5:36 AM

3
RICH 4:50 AM
DELN 4:54 AM
PLZA 4:57 AM
NBRK 5:00 AM
DBRK 5:03 AM
ASHB 5:05 AM
MCAR 5:08 AM
19TH 5:14 AM
12TH 5:15 AM
LAKE 5:18 AM
FTVL 5:22 AM
COLS 5:25 AM
SANL 5:29 AM
BAYF 5:33 AM
HAYW 5:37 AM
SHAY 5:41 AM
UCTY 5:46 AM
FRMT 5:51 AM

4
RICH 5:05 AM
DELN 5:09 AM
PLZA 5:12 AM
NBRK 5:15 AM
DBRK 5:18 AM
ASHB 5:20 AM
MCAR 5:23 AM
19TH 5:29 AM
12TH 5:30 AM
LAKE 5:33 AM
FTVL 5:37 AM
COLS 5:40 AM
SANL 5:44 AM
BAYF 5:48 AM
HAYW 5:52 AM
SHAY 5:56 AM
UCTY 6:01 AM
FRMT 6:06 AM

5
RICH 5:20 AM
DELN 5:24 AM
PLZA 5:27 AM
NBRK 5:30 AM
DBRK 5:33 AM
ASHB 5:35 AM
MCAR 5:38 AM
19TH 5:44 AM
12TH 5:45 AM
LAKE 5:48 AM
FTVL 5:52 AM
COLS 5:55 AM
SANL 5:59 AM
BAYF 6:03 AM
HAYW 6:07 AM
SHAY 6:11 AM
UCTY 6:16 AM
FRMT 6:21 AM

6
RICH 5:35 AM
DELN 5:39 AM
PLZA 5:42 AM
NBRK 5:45 AM
DBRK 5:48 AM
ASHB 5:50 AM
MCAR 5:53 AM
19TH 5:59 AM
12TH 6:00 AM
LAKE 6:03 AM
FTVL 6:07 AM
COLS 6:10 AM
SANL 6:14 AM
BAYF 6:18 AM
HAYW 6:22 AM
SHAY 6:26 AM
UCTY 6:31 AM
FRMT 6:36 AM

7
RICH 5:50 AM
DELN 5:54 AM
PLZA 5:57 AM
NBRK 6:00 AM
DBRK 6:03 AM
ASHB 6:05 AM
MCAR 6:08 AM
19TH 6:14 AM
12TH 6:15 AM
LAKE 6:18 AM
FTVL 6:22 AM
COLS 6:25 AM
SANL 6:29 AM
BAYF 6:33 AM
HAYW 6:37 AM
SHAY 6:41 AM
UCTY 6:46 AM
FRMT 6:51 AM

8
RICH 6:05 AM
DELN 6:09 AM
PLZA 6:12 AM
NBRK 6:15 AM
DBRK 6:18 AM
ASHB 6:20 AM
MCAR 6:23 AM
19TH 6:29 AM
12TH 6:30 AM
LAKE 6:33 AM
FTVL 6:37 AM
COLS 6:40 AM
SANL 6:44 AM
BAYF 6:48 AM
HAYW 6:52 AM
SHAY 6:56 AM
UCTY 7:01 AM
FRMT 7:06 AM

9
RICH 6:20 AM
DELN 6:24 AM
PLZA 6:27 AM
NBRK 6:30 AM
DBRK 6:33 AM
ASHB 6:35 AM
MCAR 6:38 AM
19TH 6:44 AM
12TH 6:45 AM
LAKE 6:48 AM
FTVL 6:52 AM
COLS 6:55 AM
SANL 6:59 AM
BAYF 7:03 AM
HAYW 7:07 AM
SHAY 7:11 AM
UCTY 7:16 AM
FRMT 7:21 AM

10
RICH 6:35 AM
DELN 6:39 AM
PLZA 6:42 AM
NBRK 6:45 AM
DBRK 6:48 AM
ASHB 6:50 AM
MCAR 6:53 AM
19TH 6:59 AM
12TH 7:00 AM
LAKE 7:03 AM
FTVL 7:07 AM
COLS 7:10 AM
SANL 7:14 AM
BAYF 7:18 AM
HAYW 7:22 AM
SHAY 7:26 AM
UCTY 7:31 AM
FRMT 7:36 AM

11
RICH 6:50 AM
DELN 6:54 AM
PLZA 6:57 AM
NBRK 7:00 AM
DBRK 7:03 AM
ASHB 7:05 AM
MCAR 7:08 AM
19TH 7:14 AM
12TH 7:15 AM
LAKE 7:18 AM
FTVL 7:22 AM
COLS 7:25 AM
SANL 7:29 AM
BAYF 7:33 AM
HAYW 7:37 AM
SHAY 7:41 AM
UCTY 7:46 AM
FRMT 7:51 AM

12
RICH 7:05 AM
DELN 7:09 AM
PLZA 7:12 AM
NBRK 7:15 AM
DBRK 7:18 AM
ASHB 7:20 AM
MCAR 7:23 AM
19TH 7:29 AM
12TH 7:30 AM
LAKE 7:33 AM
FTVL 7:37 AM
COLS 7:40 AM
SANL 7:44 AM
BAYF 7:48 AM
HAYW 7:52 AM
SHAY 7:56 AM
UCTY 8:01 AM
FRMT 8:06 AM

13
RICH 7:20 AM
DELN 7:24 AM
PLZA 7:27 AM
NBRK 7:30 AM
DBRK 7:33 AM
ASHB 7:35 AM
MCAR 7:38 AM
19TH 7:44 AM
12TH 7:45 AM
LAKE 7:48 AM
FTVL 7:52 AM
COLS 7:55 AM
SANL 7:59 AM
BAYF 8:03 AM
HAYW 8:07 AM
SHAY 8:11 AM
UCTY 8:16 AM
FRMT 8:21 AM

14
RICH 7:35 AM
DELN 7:39 AM
PLZA 7:42 AM
NBRK 7:45 AM
DBRK 7:48 AM
ASHB 7:50 AM
MCAR 7:53 AM
19TH 7:59 AM
12TH 8:00 AM
LAKE 8:03 AM
FTVL 8:07 AM
COLS 8:10 AM
SANL 8:14 AM
BAYF 8:18 AM
HAYW 8:22 AM
SHAY 8:26 AM
UCTY 8:31 AM
FRMT 8:36 AM

15
RICH 7:50 AM
DELN 7:54 AM
PLZA 7:57 AM
NBRK 8:00 AM
DBRK 8:03 AM
ASHB 8:05 AM
MCAR 8:08 AM
19TH 8:14 AM
12TH 8:15 AM
LAKE 8:18 AM
FTVL 8:22 AM
COLS 8:25 AM
SANL 8:29 AM
BAYF 8:33 AM
HAYW 8:37 AM
SHAY 8:41 AM
UCTY 8:46 AM
FRMT 8:51 AM

16
RICH 8:05 AM
DELN 8:09 AM
PLZA 8:12 AM
NBRK 8:15 AM
DBRK 8:18 AM
ASHB 8:20 AM
MCAR 8:23 AM
19TH 8:29 AM
12TH 8:30 AM
LAKE 8:33 AM
FTVL 8:37 AM
COLS 8:40 AM
SANL 8:44 AM
BAYF 8:48 AM
HAYW 8:52 AM
SHAY 8:56 AM
UCTY 9:01 AM
FRMT 9:06 AM

17
RICH 8:20 AM
DELN 8:24 AM
PLZA 8:27 AM
NBRK 8:30 AM
DBRK 8:33 AM
ASHB 8:35 AM
MCAR 8:38 AM
19TH 8:44 AM
12TH 8:45 AM
LAKE 8:48 AM
FTVL 8:52 AM
COLS 8:55 AM
SANL 8:59 AM
BAYF 9:03 AM
HAYW 9:07 AM
SHAY 9:11 AM
UCTY 9:16 AM
FRMT 9:21 AM

18
RICH 8:35 AM
DELN 8:39 AM
PLZA 8:42 AM
NBRK 8:45 AM
DBRK 8:48 AM
ASHB 8:50 AM
MCAR 8:53 AM
19TH 8:59 AM
12TH 9:00 AM
LAKE 9:03 AM
FTVL 9:07 AM
COLS 9:10 AM
SANL 9:14 AM
BAYF 9:18 AM
HAYW 9:22 AM
SHAY 9:26 AM
UCTY 9:31 AM
FRMT 9:36 AM

19
RICH 8:50 AM
DELN 8:54 AM
PLZA 8:57 AM
NBRK 9:00 AM
DBRK 9:03 AM
ASHB 9:05 AM
MCAR 9:08 AM
19TH 9:14 AM
12TH 9:15 AM
LAKE 9:18 AM
FTVL 9:22 AM
COLS 9:25 AM
SANL 9:29 AM
BAYF 9:33 AM
HAYW 9:37 AM
SHAY 9:41 AM
UCTY 9:46 AM
FRMT 9:51 AM

20
RICH 9:05 AM
DELN 9:09 AM
PLZA 9:12 AM
NBRK 9:15 AM
DBRK 9:18 AM
ASHB 9:20 AM
MCAR 9:23 AM
19TH 9:29 AM
12TH 9:30 AM
LAKE 9:33 AM
FTVL 9:37 AM
COLS 9:40 AM
SANL 9:44 AM
BAYF 9:48 AM
HAYW 9:52 AM
SHAY 9:56 AM
UCTY 10:01 AM
FRMT 10:06 AM

21
RICH 9:20 AM
DELN 9:24 AM
PLZA 9:27 AM
NBRK 9:30 AM
DBRK 9:33 AM
ASHB 9:35 AM
MCAR 9:38 AM
19TH 9:44 AM
12TH 9:45 AM
LAKE 9:48 AM
FTVL 9:52 AM
COLS 9:55 AM
SANL 9:59 AM
BAYF 10:03 AM
HAYW 10:07 AM
SHAY 10:11 AM
UCTY 10:16 AM
FRMT 10:21 AM

22
RICH 9:35 AM
DELN 9:39 AM
PLZA 9:42 AM
NBRK 9:45 AM
DBRK 9:48 AM
ASHB 9:50 AM
MCAR 9:53 AM
19TH 9:59 AM
12TH 10:00 AM
LAKE 10:03 AM
FTVL 10:07 AM
COLS 10:10 AM
SANL 10:14 AM
BAYF 10:18 AM
HAYW 10:22 AM
SHAY 10:26 AM
UCTY 10:31 AM
FRMT 10:36 AM

23
RICH 9:50 AM
DELN 9:54 AM
PLZA 9:57 AM
NBRK 10:00 AM
DBRK 10:03 AM
ASHB 10:05 AM
MCAR 10:08 AM
19TH 10:14 AM
12TH 10:15 AM
LAKE 10:18 AM
FTVL 10:22 AM
COLS 10:25 AM
SANL 10:29 AM
BAYF 10:33 AM
HAYW 10:37 AM
SHAY 10:41 AM
UCTY 10:46 AM
FRMT 10:51 AM

24
RICH 10:05 AM
DELN 10:09 AM
PLZA 10:12 AM
NBRK 10:15 AM
DBRK 10:18 AM
ASHB 10:20 AM
MCAR 10:23 AM
19TH 10:29 AM
12TH 10:30 AM
LAKE 10:33 AM
FTVL 10:37 AM
COLS 10:40 AM
SANL 10:44 AM
BAYF 10:48 AM
HAYW 10:52 AM
SHAY 10:56 AM
UCTY 11:01 AM
FRMT 11:06 AM

25
RICH 10:20 AM
DELN 10:24 AM
PLZA 10:27 AM
NBRK 10:30 AM
DBRK 10:33 AM
ASHB 10:35 AM
MCAR 10:38 AM
19TH 10:44 AM
12TH 10:45 AM
LAKE 10:48 AM
FTVL 10:52 AM
COLS 10:55 AM
SANL 10:59 AM
BAYF 11:03 AM
HAYW 11:07 AM
SHAY 11:11 AM
UCTY 11:16 AM
FRMT 11:21 AM

26
RICH 10:35 AM
DELN 10:39 AM
PLZA 10:42 AM
NBRK 10:45 AM
DBRK 10:48 AM
ASHB 10:50 AM
MCAR 10:53 AM
19TH 10:59 AM
12TH 11:00 AM
LAKE 11:03 AM
FTVL 11:07 AM
COLS 11:10 AM
SANL 11:14 AM
BAYF 11:18 AM
HAYW 11:22 AM
SHAY 11:26 AM
UCTY 11:31 AM
FRMT 11:36 AM

27
RICH 10:50 AM
DELN 10:54 AM
PLZA 10:57 AM
NBRK 11:00 AM
DBRK 11:03 AM
ASHB 11:05 AM
MCAR 11:08 AM
19TH 11:14 AM
12TH 11:15 AM
LAKE 11:18 AM
FTVL 11:22 AM
COLS 11:25 AM
SANL 11:29 AM
BAYF 11:33 AM
HAYW 11:37 AM
SHAY 11:41 AM
UCTY 11:46 AM
FRMT 11:51 AM

28
RICH 11:05 AM
DELN 11:09 AM
PLZA 11:12 AM
NBRK 11:15 AM
DBRK 11:18 AM
ASHB 11:20 AM
MCAR 11:23 AM
19TH 11:29 AM
12TH 11:30 AM
LAKE 11:33 AM
FTVL 11:37 AM
COLS 11:40 AM
SANL 11:44 AM
BAYF 11:48 AM
HAYW 11:52 AM
SHAY 11:56 AM
UCTY 12:01 PM
FRMT 12:06 PM

29
RICH 11:20 AM
DELN 11:24 AM
PLZA 11:27 AM
NBRK 11:30 AM
DBRK 11:33 AM
ASHB 11:35 AM
MCAR 11:38 AM
19TH 11:44 AM
12TH 11:45 AM
LAKE 11:48 AM
FTVL 11:52 AM
COLS 11:55 AM
SANL 11:59 AM
BAYF 12:03 PM
HAYW 12:07 PM
SHAY 12:11 PM
UCTY 12:16 PM
FRMT 12:21 PM

30
RICH 11:35 AM
DELN 11:39 AM
PLZA 11:42 AM
NBRK 11:45 AM
DBRK 11:48 AM
ASHB 11:50 AM
MCAR 11:53 AM
19TH 11:59 AM
12TH 12:00 PM
LAKE 12:03 PM
FTVL 12:07 PM
COLS 12:10 PM
SANL 12:14 PM
BAYF 12:18 PM
HAYW 12:22 PM
SHAY 12:26 PM
UCTY 12:31 PM
FRMT 12:36 PM

31
RICH 11:50 AM
DELN 11:54 AM
PLZA 11:57 AM
NBRK 12:00 PM
DBRK 12:03 PM
ASHB 12:05 PM
MCAR 12:08 PM
19TH 12:14 PM
12TH 12:15 PM
LAKE 12:18 PM
FTVL 12:22 PM
COLS 12:25 PM
SANL 12:29 PM
BAYF 12:33 PM
HAYW 12:37 PM
SHAY 12:41 PM
UCTY 12:46 PM
FRMT 12:51 PM

32
RICH 12:05 PM
DELN 12:09 PM
PLZA 12:12 PM
NBRK 12:15 PM
DBRK 12:18 PM
ASHB 12:20 PM
MCAR 12:23 PM
19TH 12:29 PM
12TH 12:30 PM
LAKE 12:33 PM
FTVL 12:37 PM
COLS 12:40 PM
SANL 12:44 PM
BAYF 12:48 PM
HAYW 12:52 PM
SHAY 12:56 PM
UCTY 1:01 PM
FRMT 1:06 PM

33
RICH 12:20 PM
DELN 12:24 PM
PLZA 12:27 PM
NBRK 12:30 PM
DBRK 12:33 PM
ASHB 12:35 PM
MCAR 12:38 PM
19TH 12:44 PM
12TH 12:45 PM
LAKE 12:48 PM
FTVL 12:52 PM
COLS 12:55 PM
SANL 12:59 PM
BAYF 1:03 PM
HAYW 1:07 PM
SHAY 1:11 PM
UCTY 1:16 PM
FRMT 1:21 PM

34
RICH 12:35 PM
DELN 12:39 PM
PLZA 12:42 PM
NBRK 12:45 PM
DBRK 12:48 PM
ASHB 12:50 PM
MCAR 12:53 PM
19TH 12:59 PM
12TH 1:00 PM
LAKE 1:03 PM
FTVL 1:07 PM
COLS 1:10 PM
SANL 1:14 PM
BAYF 1:18 PM
HAYW 1:22 PM
SHAY 1:26 PM
UCTY 1:31 PM
FRMT 1:36 PM

35
RICH 12:50 PM
DELN 12:54 PM
PLZA 12:57 PM
NBRK 1:00 PM
DBRK 1:03 PM
ASHB 1:05 PM
MCAR 1:08 PM
19TH 1:14 PM
12TH 1:15 PM
LAKE 1:18 PM
FTVL 1:22 PM
COLS 1:25 PM
SANL 1:29 PM
BAYF 1:33 PM
HAYW 1:37 PM
SHAY 1:41 PM
UCTY 1:46 PM
FRMT 1:51 PM

36
RICH 1:05 PM
DELN 1:09 PM
PLZA 1:12 PM
NBRK 1:15 PM
DBRK 1:18 PM
ASHB 1:20 PM
MCAR 1:23 PM
19TH 1:29 PM
12TH 1:30 PM
LAKE 1:33 PM
FTVL 1:37 PM
COLS 1:40 PM
SANL 1:44 PM
BAYF 1:48 PM
HAYW 1:52 PM
SHAY 1:56 PM
UCTY 2:01 PM
FRMT 2:06 PM

37
RICH 1:20 PM
DELN 1:24 PM
PLZA 1:27 PM
NBRK 1:30 PM
DBRK 1:33 PM
ASHB 1:35 PM
MCAR 1:38 PM
19TH 1:44 PM
12TH 1:45 PM
LAKE 1:48 PM
FTVL 1:52 PM
COLS 1:55 PM
SANL 1:59 PM
BAYF 2:03 PM
HAYW 2:07 PM
SHAY 2:11 PM
UCTY 2:16 PM
FRMT 2:21 PM

38
RICH 1:35 PM
DELN 1:39 PM
PLZA 1:42 PM
NBRK 1:45 PM
DBRK 1:48 PM
ASHB 1:50 PM
MCAR 1:53 PM
19TH 1:59 PM
12TH 2:00 PM
LAKE 2:03 PM
FTVL 2:07 PM
COLS 2:10 PM
SANL 2:14 PM
BAYF 2:18 PM
HAYW 2:22 PM
SHAY 2:26 PM
UCTY 2:31 PM
FRMT 2:36 PM

39
RICH 1:50 PM
DELN 1:54 PM
PLZA 1:57 PM
NBRK 2:00 PM
DBRK 2:03 PM
ASHB 2:05 PM
MCAR 2:08 PM
19TH 2:14 PM
12TH 2:15 PM
LAKE 2:18 PM
FTVL 2:22 PM
COLS 2:25 PM
SANL 2:29 PM
BAYF 2:33 PM
HAYW 2:37 PM
SHAY 2:41 PM
UCTY 2:46 PM
FRMT 2:51 PM

40
RICH 2:05 PM
DELN 2:09 PM
PLZA 2:12 PM
NBRK 2:15 PM
DBRK 2:18 PM
ASHB 2:20 PM
MCAR 2:23 PM
19TH 2:29 PM
12TH 2:30 PM
LAKE 2:33 PM
FTVL 2:37 PM
COLS 2:40 PM
SANL 2:44 PM
BAYF 2:48 PM
HAYW 2:52 PM
SHAY 2:56 PM
UCTY 3:01 PM
FRMT 3:06 PM

41
RICH 2:20 PM
DELN 2:24 PM
PLZA 2:27 PM
NBRK 2:30 PM
DBRK 2:33 PM
ASHB 2:35 PM
MCAR 2:38 PM
19TH 2:44 PM
12TH 2:45 PM
LAKE 2:48 PM
FTVL 2:52 PM
COLS 2:55 PM
SANL 2:59 PM
BAYF 3:03 PM
HAYW 3:07 PM
SHAY 3:11 PM
UCTY 3:16 PM
FRMT 3:21 PM

42
RICH 2:35 PM
DELN 2:39 PM
PLZA 2:42 PM
NBRK 2:45 PM
DBRK 2:48 PM
ASHB 2:50 PM
MCAR 2:53 PM
19TH 2:59 PM
12TH 3:00 PM
LAKE 3:03 PM
FTVL 3:07 PM
COLS 3:10 PM
SANL 3:14 PM
BAYF 3:18 PM
HAYW 3:22 PM
SHAY 3:26 PM
UCTY 3:31 PM
FRMT 3:36 PM

43
RICH 2:50 PM
DELN 2:54 PM
PLZA 2:57 PM
NBRK 3:00 PM
DBRK 3:03 PM
ASHB 3:05 PM
MCAR 3:08 PM
19TH 3:14 PM
12TH 3:15 PM
LAKE 3:18 PM
FTVL 3:22 PM
COLS 3:25 PM
SANL 3:29 PM
BAYF 3:33 PM
HAYW 3:37 PM
SHAY 3:41 PM
UCTY 3:46 PM
FRMT 3:51 PM

44
RICH 3:05 PM
DELN 3:09 PM
PLZA 3:12 PM
NBRK 3:15 PM
DBRK 3:18 PM
ASHB 3:20 PM
MCAR 3:23 PM
19TH 3:29 PM
12TH 3:30 PM
LAKE 3:33 PM
FTVL 3:37 PM
COLS 3:40 PM
SANL 3:44 PM
BAYF 3:48 PM
HAYW 3:52 PM
SHAY 3:56 PM
UCTY 4:01 PM
FRMT 4:06 PM

45
RICH 3:20 PM
DELN 3:24 PM
PLZA 3:27 PM
NBRK 3:30 PM
DBRK 3:33 PM
ASHB 3:35 PM
MCAR 3:38 PM
19TH 3:44 PM
12TH 3:45 PM
LAKE 3:48 PM
FTVL 3:52 PM
COLS 3:55 PM
SANL 3:59 PM
BAYF 4:03 PM
HAYW 4:07 PM
SHAY 4:11 PM
UCTY 4:16 PM
FRMT 4:21 PM

46
RICH 3:35 PM
DELN 3:39 PM
PLZA 3:42 PM
NBRK 3:45 PM
DBRK 3:48 PM
ASHB 3:50 PM
MCAR 3:53 PM
19TH 3:59 PM
12TH 4:00 PM
LAKE 4:03 PM
FTVL 4:07 PM
COLS 4:10 PM
SANL 4:14 PM
BAYF 4:18 PM
HAYW 4:22 PM
SHAY 4:26 PM
UCTY 4:31 PM
FRMT 4:36 PM

47
RICH 3:50 PM
DELN 3:54 PM
PLZA 3:57 PM
NBRK 4:00 PM
DBRK 4:03 PM
ASHB 4:05 PM
MCAR 4:08 PM
19TH 4:14 PM
12TH 4:15 PM
LAKE 4:18 PM
FTVL 4:22 PM
COLS 4:25 PM
SANL 4:29 PM
BAYF 4:33 PM
HAYW 4:37 PM
SHAY 4:41 PM
UCTY 4:46 PM
FRMT 4:51 PM

48
RICH 4:05 PM
DELN 4:09 PM
PLZA 4:12 PM
NBRK 4:15 PM
DBRK 4:18 PM
ASHB 4:20 PM
MCAR 4:23 PM
19TH 4:29 PM
12TH 4:30 PM
LAKE 4:33 PM
FTVL 4:37 PM
COLS 4:40 PM
SANL 4:44 PM
BAYF 4:48 PM
HAYW 4:52 PM
SHAY 4:56 PM
UCTY 5:01 PM
FRMT 5:06 PM

49
RICH 4:20 PM
DELN 4:24 PM
PLZA 4:27 PM
NBRK 4:30 PM
DBRK 4:33 PM
ASHB 4:35 PM
MCAR 4:38 PM
19TH 4:44 PM
12TH 4:45 PM
LAKE 4:48 PM
FTVL 4:52 PM
COLS 4:55 PM
SANL 4:59 PM
BAYF 5:03 PM
HAYW 5:07 PM
SHAY 5:11 PM
UCTY 5:16 PM
FRMT 5:21 PM

50
RICH 4:35 PM
DELN 4:39 PM
PLZA 4:42 PM
NBRK 4:45 PM
DBRK 4:48 PM
ASHB 4:50 PM
MCAR 4:53 PM
19TH 4:59 PM
12TH 5:00 PM
LAKE 5:03 PM
FTVL 5:07 PM
COLS 5:10 PM
SANL 5:14 PM
BAYF 5:18 PM
HAYW 5:22 PM
SHAY 5:26 PM
UCTY 5:31 PM
FRMT 5:36 PM

51
RICH 4:50 PM
DELN 4:54 PM
PLZA 4:57 PM
NBRK 5:00 PM
DBRK 5:03 PM
ASHB 5:05 PM
MCAR 5:08 PM
19TH 5:14 PM
12TH 5:15 PM
LAKE 5:18 PM
FTVL 5:22 PM
COLS 5:25 PM
SANL 5:29 PM
BAYF 5:33 PM
HAYW 5:37 PM
SHAY 5:41 PM
UCTY 5:46 PM
FRMT 5:51 PM

52
RICH 5:05 PM
DELN 5:09 PM
PLZA 5:12 PM
NBRK 5:15 PM
DBRK 5:18 PM
ASHB 5:20 PM
MCAR 5:23 PM
19TH 5:29 PM
12TH 5:30 PM
LAKE 5:33 PM
FTVL 5:37 PM
COLS 5:40 PM
SANL 5:44 PM
BAYF 5:48 PM
HAYW 5:52 PM
SHAY 5:56 PM
UCTY 6:01 PM
FRMT 6:06 PM

53
RICH 5:20 PM
DELN 5:24 PM
PLZA 5:27 PM
NBRK 5:30 PM
DBRK 5:33 PM
ASHB 5:35 PM
MCAR 5:38 PM
19TH 5:44 PM
12TH 5:45 PM
LAKE 5:48 PM
FTVL 5:52 PM
COLS 5:55 PM
SANL 5:59 PM
BAYF 6:03 PM
HAYW 6:07 PM
SHAY 6:11 PM
UCTY 6:16 PM
FRMT 6:21 PM

54
RICH 5:35 PM
DELN 5:39 PM
PLZA 5:42 PM
NBRK 5:45 PM
DBRK 5:48 PM
ASHB 5:50 PM
MCAR 5:53 PM
19TH 5:59 PM
12TH 6:00 PM
LAKE 6:03 PM
FTVL 6:07 PM
COLS 6:10 PM
SANL 6:14 PM
BAYF 6:18 PM
HAYW 6:22 PM
SHAY 6:26 PM
UCTY 6:31 PM
FRMT 6:36 PM

55
RICH 5:50 PM
DELN 5:54 PM
PLZA 5:57 PM
NBRK 6:00 PM
DBRK 6:03 PM
ASHB 6:05 PM
MCAR 6:08 PM
19TH 6:14 PM
12TH 6:15 PM
LAKE 6:18 PM
FTVL 6:22 PM
COLS 6:25 PM
SANL 6:29 PM
BAYF 6:33 PM
HAYW 6:37 PM
SHAY 6:41 PM
UCTY 6:46 PM
FRMT 6:51 PM

56
RICH 6:05 PM
DELN 6:09 PM
PLZA 6:12 PM
NBRK 6:15 PM
DBRK 6:18 PM
ASHB 6:20 PM
MCAR 6:23 PM
19TH 6:29 PM
12TH 6:30 PM
LAKE 6:33 PM
FTVL 6:37 PM
COLS 6:40 PM
SANL 6:44 PM
BAYF 6:48 PM
HAYW 6:52 PM
SHAY 6:56 PM
UCTY 7:01 PM
FRMT 7:06 PM

57
RICH 6:20 PM
DELN 6:24 PM
PLZA 6:27 PM
NBRK 6:30 PM
DBRK 6:33 PM
ASHB 6:35 PM
MCAR 6:38 PM
19TH 6:44 PM
12TH 6:45 PM
LAKE 6:48 PM
FTVL 6:52 PM
COLS 6:55 PM
SANL 6:59 PM
BAYF 7:03 PM
HAYW 7:07 PM
SHAY 7:11 PM
UCTY 7:16 PM
FRMT 7:21 PM

58
RICH 6:35 PM
DELN 6:39 PM
PLZA 6:42 PM
NBRK 6:45 PM
DBRK 6:48 PM
ASHB 6:50 PM
MCAR 6:53 PM
19TH 6:59 PM
12TH 7:00 PM
LAKE 7:03 PM
FTVL 7:07 PM
COLS 7:10 PM
SANL 7:14 PM
BAYF 7:18 PM
HAYW 7:22 PM
SHAY 7:26 PM
UCTY 7:31 PM
FRMT 7:36 PM

59
RICH 6:50 PM
DELN 6:54 PM
PLZA 6:57 PM
NBRK 7:00 PM
DBRK 7:03 PM
ASHB 7:05 PM
MCAR 7:08 PM
19TH 7:14 PM
12TH 7:15 PM
LAKE 7:18 PM
FTVL 7:22 PM
COLS 7:25 PM
SANL 7:29 PM
BAYF 7:33 PM
HAYW 7:37 PM
SHAY 7:41 PM
UCTY 7:46 PM
FRMT 7:51 PM

60
RICH 7:05 PM
DELN 7:09 PM
PLZA 7:12 PM
NBRK 7:15 PM
DBRK 7:18 PM
ASHB 7:20 PM
MCAR 7:23 PM
19TH 7:29 PM
12TH 7:30 PM
LAKE 7:33 PM
FTVL 7:37 PM
COLS 7:40 PM
SANL 7:44 PM
BAYF 7:48 PM
HAYW 7:52 PM
SHAY 7:56 PM
UCTY 8:01 PM
FRMT 8:06 PM

61
RICH 7:20 PM
DELN 7:24 PM
PLZA 7:27 PM
NBRK 7:30 PM
DBRK 7:33 PM
ASHB 7:35 PM
MCAR 7:38 PM
19TH 7:44 PM
12TH 7:45 PM
LAKE 7:48 PM
FTVL 7:52 PM
COLS 7:55 PM
SANL 7:59 PM
BAYF 8:03 PM
HAYW 8:07 PM
SHAY 8:11 PM
UCTY 8:16 PM
FRMT 8:21 PM

62
RICH 7:35 PM
DELN 7:39 PM
PLZA 7:42 PM
NBRK 7:46 PM
DBRK 7:48 PM
ASHB 7:50 PM
MCAR 7:55 PM
19TH 8:01 PM
12TH 8:02 PM
LAKE 8:05 PM
FTVL 8:09 PM
COLS 8:12 PM
SANL 8:16 PM
BAYF 8:20 PM
HAYW 8:24 PM
SHAY 8:28 PM
UCTY 8:33 PM
FRMT 8:38 PM

63
RICH 7:55 PM
DELN 7:59 PM
PLZA 8:02 PM
NBRK 8:06 PM
DBRK 8:08 PM
ASHB 8:10 PM
MCAR 8:15 PM
19TH 8:21 PM
12TH 8:22 PM
LAKE 8:25 PM
FTVL 8:29 PM
COLS 8:32 PM
SANL 8:36 PM
BAYF 8:40 PM
HAYW 8:44 PM
SHAY 8:48 PM
UCTY 8:53 PM
FRMT 8:58 PM

64
RICH 8:15 PM
DELN 8:19 PM
PLZA 8:22 PM
NBRK 8:26 PM
DBRK 8:28 PM
ASHB 8:30 PM
MCAR 8:35 PM
19TH 8:41 PM
12TH 8:42 PM
LAKE 8:45 PM
FTVL 8:49 PM
COLS 8:52 PM
SANL 8:56 PM
BAYF 9:00 PM
HAYW 9:04 PM
SHAY 9:08 PM
UCTY 9:13 PM
FRMT 9:18 PM

65
RICH 8:35 PM
DELN 8:39 PM
PLZA 8:42 PM
NBRK 8:46 PM
DBRK 8:48 PM
ASHB 8:50 PM
MCAR 8:55 PM
19TH 9:01 PM
12TH 9:02 PM
LAKE 9:05 PM
FTVL 9:09 PM
COLS 9:12 PM
SANL 9:16 PM
BAYF 9:20 PM
HAYW 9:24 PM
SHAY 9:28 PM
UCTY 9:33 PM
FRMT 9:38 PM

66
RICH 8:55 PM
DELN 8:59 PM
PLZA 9:02 PM
NBRK 9:06 PM
DBRK 9:08 PM
ASHB 9:10 PM
MCAR 9:15 PM
19TH 9:21 PM
12TH 9:22 PM
LAKE 9:25 PM
FTVL 9:29 PM
COLS 9:32 PM
SANL 9:36 PM
BAYF 9:40 PM
HAYW 9:44 PM
SHAY 9:48 PM
UCTY 9:53 PM
FRMT 9:58 PM

67
RICH 9:15 PM
DELN 9:19 PM
PLZA 9:22 PM
NBRK 9:26 PM
DBRK 9:28 PM
ASHB 9:30 PM
MCAR 9:35 PM
19TH 9:41 PM
12TH 9:42 PM
LAKE 9:45 PM
FTVL 9:49 PM
COLS 9:52 PM
SANL 9:56 PM
BAYF 10:00 PM
HAYW 10:04 PM
SHAY 10:08 PM
UCTY 10:13 PM
FRMT 10:18 PM

68
RICH 9:35 PM
DELN 9:39 PM
PLZA 9:42 PM
NBRK 9:46 PM
DBRK 9:48 PM
ASHB 9:50 PM
MCAR 9:55 PM
19TH 10:01 PM
12TH 10:02 PM
LAKE 10:05 PM
FTVL 10:09 PM
COLS 10:12 PM
SANL 10:16 PM
BAYF 10:20 PM
HAYW 10:24 PM
SHAY 10:28 PM
UCTY 10:33 PM
FRMT 10:38 PM

69
RICH 9:55 PM
DELN 9:59 PM
PLZA 10:02 PM
NBRK 10:06 PM
DBRK 10:08 PM
ASHB 10:10 PM
MCAR 10:15 PM
19TH 10:21 PM
12TH 10:22 PM
LAKE 10:25 PM
FTVL 10:29 PM
COLS 10:32 PM
SANL 10:36 PM
BAYF 10:40 PM
HAYW 10:44 PM
SHAY 10:48 PM
UCTY 10:53 PM
FRMT 10:58 PM

70
RICH 10:15 PM
DELN 10:19 PM
PLZA 10:22 PM
NBRK 10:26 PM
DBRK 10:28 PM
ASHB 10:30 PM
MCAR 10:35 PM
19TH 10:41 PM
12TH 10:42 PM
LAKE 10:45 PM
FTVL 10:49 PM
COLS 10:52 PM
SANL 10:56 PM
BAYF 11:00 PM
HAYW 11:04 PM
SHAY 11:08 PM
UCTY 11:13 PM
FRMT 11:18 PM

71
RICH 10:35 PM
DELN 10:39 PM
PLZA 10:42 PM
NBRK 10:46 PM
DBRK 10:48 PM
ASHB 10:50 PM
MCAR 10:55 PM
19TH 11:01 PM
12TH 11:02 PM
LAKE 11:05 PM
FTVL 11:09 PM
COLS 11:12 PM
SANL 11:16 PM
BAYF 11:20 PM
HAYW 11:24 PM
SHAY 11:28 PM
UCTY 11:33 PM
FRMT 11:38 PM

72
RICH 10:55 PM
DELN 10:59 PM
PLZA 11:02 PM
NBRK 11:06 PM
DBRK 11:08 PM
ASHB 11:10 PM
MCAR 11:15 PM
19TH 11:21 PM
12TH 11:22 PM
LAKE 11:25 PM
FTVL 11:29 PM
COLS 11:32 PM
SANL 11:36 PM
BAYF 11:40 PM
HAYW 11:44 PM
SHAY 11:48 PM
UCTY 11:53 PM
FRMT 11:58 PM

73
RICH 11:15 PM
DELN 11:19 PM
PLZA 11:22 PM
NBRK 11:26 PM
DBRK 11:28 PM
ASHB 11:30 PM
MCAR 11:35 PM
19TH 11:41 PM
12TH 11:42 PM
LAKE 11:45 PM
FTVL 11:49 PM
COLS 11:52 PM
SANL 11:56 PM
BAYF 12:00 AM
HAYW 12:04 AM
SHAY 12:08 AM
UCTY 12:13 AM
FRMT 12:18 AM

74
RICH 11:35 PM
DELN 11:39 PM
PLZA 11:42 PM
NBRK 11:46 PM
DBRK 11:48 PM
ASHB 11:50 PM
MCAR 11:55 PM
19TH 12:01 AM
12TH 12:02 AM
LAKE 12:05 AM
FTVL 12:09 AM
COLS 12:12 AM
SANL 12:16 AM
BAYF 12:20 AM
HAYW 12:24 AM
SHAY 12:28 AM
UCTY 12:33 AM
FRMT 12:38 AM

75
RICH 11:55 PM
DELN 11:59 PM
PLZA 12:02 AM
NBRK 12:06 AM
DBRK 12:08 AM
ASHB 12:10 AM
MCAR 12:15 AM
19TH 12:21 AM
12TH 12:22 AM
LAKE 12:25 AM
FTVL 12:29 AM
COLS 12:32 AM
SANL 12:36 AM
BAYF 12:40 AM
HAYW 12:44 AM
SHAY 12:48 AM
UCTY 12:53 AM
FRMT 12:58 AM

76
RICH 12:17 AM
DELN 12:21 AM
PLZA 12:24 AM
NBRK 12:27 AM
DBRK 12:30 AM
ASHB 12:32 AM
MCAR 12:46 AM
19TH 12:51 AM
12TH 12:53 AM
LAKE 12:56 AM
FTVL 1:00 AM
COLS 1:03 AM
SANL 1:07 AM
BAYF 1:10 AM
HAYW 1:14 AM
SHAY 1:18 AM
UCTY 1:24 AM
FRMT 1:29 AM

Comparing schedule and real-time for a specific station

Where I'd like to go...but will ultimately leave as an exercise to you all...comparing the scheduled arrival times with the real time BART info to see how individual trains (and the system as a whole) are doing.

What we do here:

  • calculate the schedule for PLZA station
  • calculate the current real time info for PLZA station
  • figure out the difference between the real time info for the next train

Compare http://www.bart.gov/schedules/eta?stn=PLZA with http://www.bart.gov/schedules/bystationresults?station=PLZA


In [20]:
%%html
<iframe src="http://www.bart.gov/schedules/eta?stn=PLZA"/ width=800 height=600>



In [21]:
# Get schedule for PLZA

# using El Cerrito Plaza station as an example (closest station to me)
# http://www.bart.gov/stations/plza
# http://api.bart.gov/api/sched.aspx?cmd=stnsched&orig=plza&key=MW9S-E7SL-26DU-VV8V

schedule_plza_df = DataFrame(bart.get_station_schedule('PLZA'))
schedule_plza_df.head()


Out[21]:
bikeflag dest_time line orig_time train_head_station train_idx
0 1 5:21 AM ROUTE 7 4:19 AM MLBR 1
1 1 5:21 AM ROUTE 4 4:27 AM FRMT 1
2 1 5:36 AM ROUTE 7 4:34 AM MLBR 2
3 1 5:36 AM ROUTE 4 4:42 AM FRMT 2
4 1 5:51 AM ROUTE 7 4:49 AM MLBR 3

5 rows × 6 columns


In [22]:
# Get real time info for PLZA, accounting for 'Leaving', 'Arriving' in Minutes fields

# http://api.bart.gov/api/etd.aspx?cmd=etd&orig=PLZA&key=MW9S-E7SL-26DU-VV8V
# compare to http://www.bart.gov/schedules/eta?stn=PLZA

# need to handle the case of 'Leaving' and 'Arriving' given for minutes in the real time estimates

def etd_minutes_to_int(m):
    if m in ['Leaving', 'Arriving']:
        return 0
    else:
        try:
            return int(m)
        except:
            return np.nan
        

etd_plza_df = DataFrame(etd('PLZA'))
etd_plza_df['minutes'] = etd_plza_df.minutes.apply(etd_minutes_to_int)
etd_plza_df


Out[22]:
bikeflag call_dt color destination direction hexcolor length minutes platform station
0 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 6 13 2 PLZA
1 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 6 28 2 PLZA
2 1 2014-05-27 14:45:07-07:00 ORANGE FRMT South #ff9933 6 43 2 PLZA
3 1 2014-05-27 14:45:07-07:00 RED MLBR South #ff0000 5 5 2 PLZA
4 1 2014-05-27 14:45:07-07:00 RED MLBR South #ff0000 9 20 2 PLZA
5 1 2014-05-27 14:45:07-07:00 RED MLBR South #ff0000 9 35 2 PLZA
6 1 2014-05-27 14:45:07-07:00 RED RICH North #ff0000 5 1 1 PLZA
7 1 2014-05-27 14:45:07-07:00 ORANGE RICH North #ff9933 3 11 1 PLZA
8 1 2014-05-27 14:45:07-07:00 RED RICH North #ff0000 5 17 1 PLZA

9 rows × 10 columns


In [23]:
# compute the absolute time associated with real time estimate

from datetime import timedelta

etd_plza_df['estimate'] = etd_plza_df.apply(lambda s: s['call_dt'] + \
                                            timedelta(minutes=s['minutes']), axis=1)
etd_plza_df[['destination','direction','station','estimate','minutes']]


Out[23]:
destination direction station estimate minutes
0 FRMT South PLZA 2014-05-27 14:58:07-07:00 13
1 FRMT South PLZA 2014-05-27 15:13:07-07:00 28
2 FRMT South PLZA 2014-05-27 15:28:07-07:00 43
3 MLBR South PLZA 2014-05-27 14:50:07-07:00 5
4 MLBR South PLZA 2014-05-27 15:05:07-07:00 20
5 MLBR South PLZA 2014-05-27 15:20:07-07:00 35
6 RICH North PLZA 2014-05-27 14:46:07-07:00 1
7 RICH North PLZA 2014-05-27 14:56:07-07:00 11
8 RICH North PLZA 2014-05-27 15:02:07-07:00 17

9 rows × 5 columns


In [24]:
# convert scheduled time into an absolute time

from pytz import timezone
pacific_tz = timezone("US/Pacific")

def orig_time_dt(ot):
    """ """
    dt = parse(ot)
    # with rare exception, we should not find any times earlier than 4am -- if so this is the
    # next day
    # exception:  Bay Bridge repair weekend http://www.bart.gov/news/articles/2013/news20130815

    if dt.hour < 4:
        dt = dt + timedelta(days=1)

    # put dt into local timezone
    dt = pacific_tz.localize(dt)
   
    return dt

schedule_plza_df['orig_time'].apply(orig_time_dt)


Out[24]:
0     2014-05-27 04:19:00-07:00
1     2014-05-27 04:27:00-07:00
2     2014-05-27 04:34:00-07:00
3     2014-05-27 04:42:00-07:00
4     2014-05-27 04:49:00-07:00
5     2014-05-27 04:53:00-07:00
6     2014-05-27 04:57:00-07:00
7     2014-05-27 05:04:00-07:00
8     2014-05-27 05:08:00-07:00
9     2014-05-27 05:12:00-07:00
10    2014-05-27 05:19:00-07:00
11    2014-05-27 05:23:00-07:00
12    2014-05-27 05:27:00-07:00
13    2014-05-27 05:34:00-07:00
14    2014-05-27 05:38:00-07:00
...
255    2014-05-27 22:22:00-07:00
256    2014-05-27 22:28:00-07:00
257    2014-05-27 22:42:00-07:00
258    2014-05-27 22:48:00-07:00
259    2014-05-27 23:02:00-07:00
260    2014-05-27 23:08:00-07:00
261    2014-05-27 23:22:00-07:00
262    2014-05-27 23:28:00-07:00
263    2014-05-27 23:42:00-07:00
264    2014-05-27 23:48:00-07:00
265    2014-05-28 00:02:00-07:00
266    2014-05-28 00:08:00-07:00
267    2014-05-28 00:24:00-07:00
268    2014-05-28 00:33:00-07:00
269    2014-05-28 00:56:00-07:00
Name: orig_time, Length: 270, dtype: object

In [25]:
# as a first pass, compare only the the next trains for each route

next_plza_trains = etd_plza_df.groupby('destination').apply(lambda s: min(s['estimate']))
next_plza_trains


Out[25]:
destination
FRMT           2014-05-27 14:58:07-07:00
MLBR           2014-05-27 14:50:07-07:00
RICH           2014-05-27 14:46:07-07:00
dtype: object

In [26]:
# do the comparison

comparisons = []

for (destination, estimate) in next_plza_trains.iterkv():
    scheduled_for_dest = schedule_plza_df[schedule_plza_df.train_head_station==destination]
    time_diff = scheduled_for_dest['orig_time'].apply(orig_time_dt) - estimate
    comparisons.append({'destination':destination,
                        'estimate':estimate,
                        'schedule':schedule_plza_df.iloc[np.argmin(abs(time_diff))]['orig_time'],
                        'diff': np.min(abs(time_diff))})
    
comparisons_df = DataFrame(comparisons)
comparisons_df


Out[26]:
destination diff estimate schedule
0 FRMT 0 00:01:07 dtype: timedelta64[ns] 2014-05-27 14:58:07-07:00 2:57 PM
1 MLBR 0 00:01:07 dtype: timedelta64[ns] 2014-05-27 14:50:07-07:00 2:49 PM
2 RICH 0 00:01:07 dtype: timedelta64[ns] 2014-05-27 14:46:07-07:00 2:45 PM

3 rows × 4 columns


In [27]:
# put it all together

# first pass at an algorithm
# for all ETD, find the minimum difference with a sechedule arrival

import requests
import urllib
from datetime import timedelta

from lxml.etree import fromstring

from dateutil.parser import parse
from dateutil.tz import tzlocal

from pandas import DataFrame
import numpy as np

import bart_api 


try:
    # to allow import of a registered key if it exists
    from settings import BART_API_KEY
except:
    BART_API_KEY = "MW9S-E7SL-26DU-VV8V"

from pytz import timezone
pacific_tz = timezone("US/Pacific")


def etd(orig, key=BART_API_KEY):
    url = "http://api.bart.gov/api/etd.aspx?" +  \
            urllib.urlencode({'cmd':'etd',
                              'orig':orig,
                              'key':key})
                                                                  
    r = requests.get(url)
    doc = fromstring(r.content)
    
    estimations_list = []

    # parse the datetime for the API call

    s = doc.find('date').text + " " +doc.find('time').text
    call_dt = parse(s)
    
    # turn the results into a rectangular format

    # parse the station

    for station in doc.findall('station'):
        etds = station.findall('etd')
        for etd in etds:
            estimates = etd.findall('estimate')
            for estimate in estimates:
                estimate_tuple = [(child.tag, child.text) for child in estimate.iterchildren()]
                
                estimate_tuple += [('call_dt', call_dt),
                                   ('station', station.find('abbr').text),
                                   ('destination', etd.find('abbreviation').text)]
               
                estimations_list.append(dict(estimate_tuple))

    return estimations_list


def etd_minutes_to_int(m):
    if m in ['Leaving', 'Arriving']:
        return 0
    else:
        try:
            return int(m)
        except:
            return np.nan
        

def orig_time_dt(ot):
    """ """
    dt = parse(ot)
    # with rare exception, we should not find any times earlier than 4am -- if so this is the
    # next day
    # exception:  Bay Bridge repair weekend http://www.bart.gov/news/articles/2013/news20130815

    if dt.hour < 4:
        dt = dt + timedelta(days=1)

    # put dt into local timezone
    dt = pacific_tz.localize(dt)
   
    return dt


bart = bart_api.BartApi(BART_API_KEY)

# using El Cerrito Plaza station as an example (closest station to me)
# http://www.bart.gov/stations/plza

# station schedule
# http://api.bart.gov/api/sched.aspx?cmd=stnsched&orig=plza&key=MW9S-E7SL-26DU-VV8V

schedule_plza_df = DataFrame(bart.get_station_schedule('PLZA'))

# http://api.bart.gov/api/etd.aspx?cmd=etd&orig=PLZA&key=MW9S-E7SL-26DU-VV8V
# compare to http://www.bart.gov/schedules/eta?stn=PLZA

etd_plza_df = DataFrame(etd('PLZA'))

# make sure minutes are integer
etd_plza_df['minutes'] = etd_plza_df.minutes.apply(etd_minutes_to_int)

# compute the absolute time of the real time estimates
etd_plza_df['estimate'] = etd_plza_df.apply(lambda s: s['call_dt'] + \
                                            timedelta(minutes=s['minutes']), axis=1)

# for each route, compute the next train coming into PLZA
next_plza_trains = etd_plza_df.groupby('destination').apply(lambda s: min(s['estimate']))

comparisons = []

for (destination, estimate) in next_plza_trains.iterkv():
    scheduled_for_dest = schedule_plza_df[schedule_plza_df.train_head_station==destination]
    time_diff = scheduled_for_dest['orig_time'].apply(orig_time_dt) - estimate
    comparisons.append({'destination':destination,
                        'estimate':estimate,
                        'schedule':schedule_plza_df.iloc[np.argmin(abs(time_diff))]['orig_time'],
                        'diff': np.min(abs(time_diff))})
    #print destination, estimate, schedule_plza_df.iloc[np.argmin(abs(time_diff))]['orig_time'], np.min(abs(time_diff))
    
comparisons_df = DataFrame(comparisons)
comparisons_df


Out[27]:
destination diff estimate schedule
0 FRMT 0 00:01:07 dtype: timedelta64[ns] 2014-05-27 14:58:07-07:00 2:57 PM
1 MLBR 0 00:01:07 dtype: timedelta64[ns] 2014-05-27 14:50:07-07:00 2:49 PM
2 RICH 0 00:01:07 dtype: timedelta64[ns] 2014-05-27 14:46:07-07:00 2:45 PM

3 rows × 4 columns

Some Next Steps

  • Generalize to all stations
  • Accumulate data over a period of time to study BART performance.
  • Compare delays we see with the alerts that come from BART itself.

Questions (I'm keeping tabs on)


In [27]: