CitySpeed - Road network efficiency via online mapping

Ever wonder if some cities are just quicker to get around in? CitySpeed is a Python package that uses the online driving directions provided by Google Maps to compute statistics on the speed and complexity of city driving, ignoring traffic. This information can be used to compare the efficiency of cities’ (or states’, or countries’...) road networks themselves, independent of how many drivers they may carry.

If you just want to see the data on the 50 largest U.S. cities, look here:

Map of U.S. showing driving speeds of several cities

By default, cityspeed will gather statistics for the 50 largest U.S. cities. For each city, it does a Google Local search for the most popular 32 elementary schools and 32 Starbucks coffee shops. It then gets driving directions from every elementary school to every Starbucks (1024 routes in total), remembering the distance, duration, and number of steps in the directions. It computes the mean and standard deviation of the speed, steps per mile, total steps, distance, and duration.

The data is collected in a set of JSON files named after each city. The files are quite human-readable and fairly self-explanatory (see sample data below). It’s also highly Web 2.0-compliant and easy to mash up with other web services. A sample dynamic Web site that reads the data and plots the cities on a Google Map, color-coded by speed, is included; you can see it in action here: http://infinitemonkeycorps.net/projects/cityspeed/

cityspeed is the main module that does the heavy lifting; it can be run as a script. You will need to edit cityspeed/settings.py to provide a Google Maps API key and a referrer URL for it to work. By default, it queries about one route every 6 seconds (per Google’s rate limit policy; this is tweakable). A full run takes about three days.

Incidentally, there’s nothing really specific to cities in the code; you can gather data on any locality Google Maps knows about (neighborhoods, states, countries...).

Installation

cityspeed requires the googlemaps module, so install that first:

$ sudo easy_install googlemaps

(You might also need simplejson for older Python versions.)

Download and unpack the distribution:

$ tar xzvf cityspeed-1.0.tar.gz

Edit cityspeed/settings.py to provide a Google Maps API key and referrer URL (you can also tweak the list of cities, the directory where data is stored, the timeout between network queries...). You can get a Google Maps API Key at http://code.google.com/apis/maps/signup.html. The referrer URL is either the website where the data you collect will be displayed or, if you are distributing software, where that software can be found.

Gathering Data

Run the script:

$ cd cityspeed

$ python cityspeed.py

Then sit back and wait... your data will come out in a directory called data/ in the package root (where you unpacked the source). It’s in JSON format, which is plain, human-readable text (and also easy to read into most programming languages). There are four files for each city; these are examples from New York, NY. Per-city statistics are in newyorkny-stats.json:

{
    "city": "New York, NY",
    "meters_per_sec_avg": 7.853421200066788,
    "meters_avg": 4535.7646484375009,
    "numroutes": 1024,
    "steps_avg": 6.6660156250000133,
    "meters_std": 2281.5505408086387,
    "steps_per_meter_std": 0.0011149269254682515,
    "filename": "newyorkny",
    "seconds_std": 213.66775487142917,
    "seconds_avg": 552.52441406250023,
    "lat": 40.756053999999999,
    "lng": -73.986951000000005,
    "meters_per_sec_std": 1.5060777594448762,
    "steps_std": 2.4701101450720526,
    "steps_per_meter_avg": 0.0018177175459248112
}

avg is the average, std is the (sample) standard deviation, and steps is the length of the list of directions.

The “from” origin addresses used in computing routes through the city are in newyorkny-from.json:

[
    {
        "city": "New York",
        "name": "P.S. 212 Midtown West School",
        "url": "http://www.google.com/local?source=uds&q=elementary...",
        "country": "US",
        "region": "NY",
        "street": "328 W 48th St",
        "postcode": "10036",
        "address": "328 W 48th St, New York, NY 10036, USA",
        "lat": 40.761552700000003,
        "lng": -73.988278899999997
    },
]

The “to” destination addresses used in computing routes through the city are in newyorkny-to.json:

[
    {
        "city": "New York",
        "name": "Starbucks",
        "url": "http://www.google.com/local?source=uds&q=Starbucks&sll=...",
        "country": "US",
        "region": "NY",
        "street": "1460 Broadway",
        "postcode": "10018",
        "address": "1460 Broadway, New York, NY 10018, USA",
        "lat": 40.7552643,
        "lng": -73.9865657
    },
]

Data on the routes themselves are in newyorkny-routes.json:

[
    {
        "seconds": 236,
        "start": "328 W 48th St, New York, NY 10036, USA",
        "meters": 945,
        "end": "1460 Broadway, New York, NY 10018, USA",
        "steps": 3
    },
    {
        "seconds": 623,
        "start": "328 W 48th St, New York, NY 10036, USA",
        "meters": 5433,
        "end": "1378 Madison Ave, New York, NY 10128, USA",
        "steps": 8
    },
]

Finally, citystats.json is the concatenation of the *-stats.json data for each city.

If your run crashes in the middle for some reason (say, Google shuts you down for too many requests in a day), just run cityspeed.py again and it will pick up where it left off. It’s smart enough save and use any existing data from previous runs. If you want to recompute the data for a particular city, just delete the .json files for that city and re-run cityspeed.py.

Sample Web Site

The CitySpeed distribution includes a sample JavaScript-powered web site to display collected data using Google Maps and in tabular form. An example is shown above. You can find it in the www directory of the source, and more information is available on the Example Dynamic Web Site page.

CitySpeed Modules

cityspeed - Main Driver, Data Collection

Calculates statistics on the driving travel time of cities.

When run as a script, will save statistics for all cities listed in settings.py to the data directory listed in settings.py (../data/ by default) in .json format. To use another settings file, pass it as the first command line argument:

python cityspeed.py /path/to/settings.py

You will need to edit settings.py to provide a Google Maps API Key and Referrer URL.

mapper - Geocoding, Local Search, Directions, Routes

Geocoding, local search, directions, route iterator, and related functions.

stats - Basic Descriptive Statistics

Simple descriptive statistics.

If you want to add your own statistic, subclass Keeper and implement Keeper.__init__(), Keeper.get(), and Keeper.update(). Then your statistic will be easy to plug in to citystats.compute_route_stats().

utils - Utility Functions

Mapping utilities.

Information

Author:John Kleint <cityspeed-list at lists sourceforge net>
Version:1.0
Date:October 17, 2009
URL:http://sourceforge.net/projects/cityspeed/
License:Lesser Affero General Public License v3
Python Versions:
 2.5+