HOME All Posts My Etsy Follow me on Mastodon for updates

How to Make Beautiful (and Helpful) Maps of Your Commute


Published August 1st, 2022 by Emily

A few years back I was trying to figure out where in the city I should move. I took public transit to work every day, and reducing my commute time factored heavily into my decision. Using Google Maps I manually plotted how long it would take to get to work in the morning from each apartment I looked at and found that some of the results were surprising.

I started to wonder if I might be neglecting certain pockets of the city because it would take a long time to get to work using the transit routes I was aware of, when in fact there might be a direct bus I didn't know about that would make it very convenient.

That curiosity back in 2017 led to several years of figuring out how to make this project work. Ironically, the first time I moved (a couple months after I first had the idea) I had figured out how to gather the data, but not how to plot it on a map. When I finally completed the map after moving, I looked at my current apartment and noticed the commute time of my block was longer than literally any other block in West Philly. After years of 45 minute commutes that could have been 30-40 minutes I vowed to never make a decision to move without consulting a map first.

Without further ado: a guide to making pretty (and helpful) maps of your commute

Below is a map of how long it takes to commute to Iffy Books in Philadelphia via public transit. This guide will teach you how to make your own map just like it.

Disclaimer

This project will require the use of both Google and Mapbox cloud services. It will also require you to have a credit card on file with Google (however, unless you do something drastically wrong you should have plenty of free credit to cover the costs of this project).

Step 1: Clone the repo

All of the code for this project can be found in this repo. Open up the repo and click on generate-map.py. Click the button that says Raw.

Right click the raw code page and select "Save as..." (or something similar). Keep the file name the same and save it in your favorite directory.

Step 2: Define bounds

This step is how you define what area your map will cover. You can make your bounds a giant circle around your target location if you wish, but I recommend using the polygon shape to exclude:

There's no sense in paying for extra API calls to map how long it takes to get to work from an island in the middle of the Schuylkill.

In general, the larger the area you select, the more API calls you will need to make. The size shown in the example is a good place to start. Using a size like this should leave you with plenty of credit to try again with a larger size if you so choose.

Here's an example of bounds of Philadelphia:

I use a website called geojson.io to map out my bounds. On the left you can use the map tool to create a polygon of your bounds. As you create the polygon, the pane in the right will auto-generate the raw geojson in text.

  1. Find the toolbar on the right side of the map and select the five-pointed shape. This is the polygon tool.
  2. Create your polygon shape by clicking on the map. Close the polygon by clicking on the first point you made.
  3. Once you're satisfied, save the shape by clicking on "Save" in the upper left toolbar and save the GeoJSON file to your desktop.
  4. In the directory where you have saved the generate-map.py file save your GeoJSON file there.
  5. Rename the file to bounds.geojson.

Step 3: Edit the script

In a moment I will show you how to edit the script to create this map, but first, a quick detour:

Quick explanation of the Google Distance Matrix API

Here is a picture of the Google Maps website when I request public transit directions between 1234 Market St and Iffy Books for an arrival time of 9 am on a Monday.

Here is a picture of the exact same request, but this time it is using Python and requesting the data via the Google Maps API. You can see that our API call replicates this request exactly.

Now take a look at the response that we get from the API request. The response has the same data that was shown to us on the website, except it only shows us the fastest route. The Distance Matrix will only show the fastest route, but you can use the Directions API if you would like to see all the possible routes and turn-by-turn directions.

In our example we will be finding the commute time between 1,379 different locations and our target location, so using the Google Maps website would be incredibly time consuming. That is why I built a script to call the API and save the results in a GeoJSON format that we can easily manipulate and upload to a mapping website.

Prerequisites: Google API Key

In order to run this script you will need an API key for the Distance Matrix and that key will need to be associated with a valid credit or debit card.

Every account gets a $300 credit for the free trial and then $200 every following month to do with what you please, and the example we're creating today only costs about $7. You should have plenty of runway to make mistakes and still not be charged. The script will also tell you approximately how much your final map will cost, and gives you the option to stop the program before you are charged. As a final safeguard, the Google Billing website allows you to keep track of how much credit you've used each month. There's really no reason that you should be charged for this project.

Note: I could be wrong about this amount of credit or it could change in the future. When you sign up for a key read everything; it should tell you the amount of credit you get. If you mess it up I'm not paying your Google Cloud bill.

To keep track of how much credit you've used, go to console.cloud.google.com. Go to the Billing tab in the left side hamburger menu, and then click Reports in the left sidebar. In the report, if you uncheck all the boxes under "Credits" you will see your actual usage.

Set up an API key for a project

If the instructions don't seem to match up, try Google's official support page.

  1. Go to Google's API Console.
  2. Agree to the terms of service.
  3. Click "Create Project" and name it whatever you want.
  4. Go to the Enabled APIs & services tab and click "+ ENABLE APIS AND SERVICES".
  5. Search for the Distance Matrix API and click on it. Click "enable".
  6. You may be required to verify your account and add a credit card number at this point.
  7. Go to the Credentials tab. If prompted, select the project you just made.
  8. Click "+ CREATE CREDENTIALS" and select to create an API key.
  9. Copy the API key to use later.
  10. Click the hamburger menu and select Billing.
  11. Click "Link A Billing Account" and then "Create a billing account".
  12. Either link an existing Billing account or create a new one.

Back to editing our script

Open up generate-map.py.

There are a few variables you will need to edit in the script.

  1. Set path_to_folder to the path to the folder that contains your script.
  2. Set resolution to how many miles you want between points. I'll go into a little more detail on this in a minute.
  3. Set api_key to the key you previously copied.
  4. Set work to the coordinates of your destination. Make sure there are no spaces between the lat and lon and that the format is longitude then latitude (this is backwards from the tranditional lat-lon format).
  5. Set transit_type to your desired type.
  6. Set set_arrival_time to your desired arrival time. The format is datetime(year,month,date,hour). This date and time must be in the future.

Resolution

When deciding on your resolution, you need to weigh the cost of having more points to plot against the needed accuracy of your map. Keep in mind that halving your resolution (going from 1 mile between points to 0.5 miles between points) will quadruple the cost of your map. A good rule of thumb is to determine how far you can get in five minutes at the beginning of your journey via your selected mode of transit.

For example, in a car exiting a neighborhood at slow speeds or in the city, you could probably get a mile in about five minutes. Via public transit, the first part of your journey is exiting your building or house and walking to the nearest transit point so you would probably only walk about 0.2 miles in five minutes. Biking is somewhere in between the two, so I recommended a resolution of 0.5 miles.

The example images below show what about 0.2 miles between points will look like on your map. It results in 1,397 total points. That many points costs about $7 to run if I'm calculating it correctly.

Step 4: Running the script

The script runs with Python 3. I won't get into how to install that here, but check out this resource for instructions on how to install Python 3 on various operating systems.

You will likely need to install dependencies. You can do that with pip. If you don't already have pip installed, refer to these instructions. Install the following dependencies:

Run the program with:

$ python generate-map.py

You may need to replace python with python3 depending on how you've installed python. If you're not in the directory that generate-map.py is located you'll need to replace generate-map.py with the full path to the file.

The program will create inpoints.geojson, show you the cost of running, and then stop and ask you to confirm that you'd like to continue with the program.

$ C:\Users\Emily\CommuteProject\ python generate-map.py
found 1379 points out of 5760 to process at 0.2 miles btwn points
this will cost 6.90 USD
Do you want to continue (y) or use existing points (n)?

Entering n will stop the program. You can actually upload the inpoints.geojson file using the next few steps to Mapbox and see what it will look like on a map and check to make sure you haven't done anything wrong.

Please note that my calculations seem to be wildly overestimating the cost of the projects. I recently ran a project that my code said was going to cost $60 and it only cost about $10. I'm going to troubleshoot this in the future, but for now try to keep your usage under $300 by checking the Billing Reports using the instructions I detailed earlier.

Entering y will then run through the list of points, and call the API for the commute times in batches of twenty. As the program runs it will print either "found results" or "no results". In the future I would like to add a safe-guard that stops the program if the first batch of results are all "no results" but I do not currently have that in the script. So if you see all "no results" being printed out in the terminal, use ctrl+c to stop the program before you waste credits on any more API calls.

The program will take the results of the API calls and add it to a geojson file that has a square around each point. The file is saved as rectangles-for-plotting.geojson.

Below shows what the resulting file will look like using geojson.io. You can see that it looks very similar to the bounds drawing you made, but instead of one large polygon you've got a collection of smaller polygons that now have defined properties. The properties contain the data from the API call for that point.

Step 5: Map your data

I use the website mapbox.com to map my data. When I first did this project back in 2020, this was the best option for me because:

Since 2020 I believe that Google has come out with their own map builder, but I haven't had a chance to test it out.

Create your map

  1. Sign up for a Mapbox account. It will require you verify your email address.
  2. Go to studio.mapbox.com and click the "New Style" button.
  3. Select your map type. I generally choose "Monochrome" with the "Light" variation because it's subtle and doesn't take away from the colors of my map, but choose whichever you prefer.
  4. Click "Customize < chosen map type >" to start editing the map.

Add your data

  1. Select the "Layers" tab in the top left of the editor.
  2. Click the "+" button to add a new layer.
  3. Click "Custom layer...", "Upload data", then "Select a file", and choose rectangles-for-plotting.geojson.
  4. Wait a minute for it to upload and process (the notification bell in the bottom right will show you the progress).
  5. After the file has fully processed, click the box that says "None selected" under "Source", just above the "Upload data" button you clicked before and find your upload. It will be named the same as in the Uploads notification.
  6. After you've selected the layer and it moves from the "Unused sources" section up to the "Active sources" section, navigate to the "Style" tab which is just above where you clicked before.
  7. At this point you should be able to see a preview of your data. You may need to move the globe to find it.

Style your data

  1. Select the "Color" pane and choose "Style across data range".
  2. Select "duration" and you'll be able to select a color range for your data.
  3. I prefer to set my "rate of change" to step, because I like the clear cut, blocky look and it makes making legends easier, but linear is the default. My screenshot above in Step 3 shows what the same map looks like with a linear rate of change.
  4. It will default to two stops, so I add the various stops and define the colors and watch as my map changes. You can see my settings below, but your exact numbers will depend on the range of your data.
  5. In the far left pane, drag your data layer almost all the way to the bottom. This will place your colors behind everything: roads, large buildings (like airports), and water. You couldn't live in those places anyway, and it will help you identify the neighborhoods better. Make sure your layer is above the land layer though, or you won't be able to see your data!

Important note: if a particular pair of coordinates returns zero_results because it is impossible to find a path between them I assign it a value of 180 minutes because all the values have to be actual numbers or Mapbox gets confused about having strings in with integers. When defining the colors, I set values of 180 equal to a transparent color, and for good measure I have a stop point at 90 minutes that's transparent as well. You can play around with what looks best to you. If for some reason 180 is a reasonable number of minutes for your commute (first off: I'm so sorry lol), you may want to ctrl+F and replace 180 with a higher number.

Step 6: Share your map

Click the publish button in the top right to save your map.

To share your map with others, click the share button that's just to the left of the publish button. Here you can send someone a link to the full-size zoomable map by sending them the "Preview only" link. Remember to select "Make public" or no one will be able to see your map.

For a static image, you can use the Print feature to export the map.

You can also embed the link in your website with the "Website embed" link. Keep in mind that Mapbox doesn't have a legend built into it. This quick and dirty way to make a legend is to use Excel and screenshot it. All the color codes translate between Mapbox and Excel.

The only way I've found to add a legend to your map and share it is to embed it onto a website. I have an example file called example-embed-map.html in the repo that you can use. Ctrl+F for "// change this" and change all the lines I have marked.

The Style URL and Access tokens are listed on the Share menu and change for each map that you make. To be clear, the Access token is the one on this map and NOT the one in your personal account API settings.

Have fun!

I hope this guide was helpful to you. If you find any mistakes, feel free to email me at emily at boda dot codes.