Plotting San Francisco Muni (SFMTA) Routes using GeoPandas

Advait
Commute Chronicles: Decoding Transportation
3 min readJul 17, 2023

In this article, I show you how to use the Geopandas and other Python libraries to plot San Francisco Public Transit routes on a map. The San Francisco Municipal Transportation Agency (SFMTA, commonly referred to as “Muni”) is a department of the City and County of San Francisco responsible for the management of all ground transportation in the city. I use publicly available data, as part of the San Francisco Open Data project to plot the maps below. The link to my code in Kaggle is at the end of this article.

Some preliminaries below for importing necessary libraries

import geopandas as gpd
import numpy as np
import pandas as pd
import shapefile as shp
import matplotlib.pyplot as plt
import seaborn as sns
import shapely.wkt
import contextily as ctx

Next, I read a dataset containing the Routes of SF Muni using the Pandas Library.

df_route = pd.read_csv("/kaggle/input/sf-open-data-transportation/Muni_Simple_Routes.csv")
df_route.head()

What is the “shape” variable though? It is in fact a set of (latitude, longitude) points that indicates the actual route of the MUNI vehicle. The line joining the points indicated in an instance of the variable is how the route is defined. Below, I examine an instance of the “shape” variable for this dataset.

df_route["shape"][0]

Below, I convert the Pandas Dataframe into GeoPandas dataframe. Note that it is important to define the “geometry” parameter of the geopandas instance, which in this case is the “shape” variable of the raw data.

gp_df_route = gpd.GeoDataFrame(df_route, geometry = df_route["shape"].apply(shapely.wkt.loads))

Below is a simple plot of the route data using the GeoPandas dataframe I created above.

gp_df_route.plot()
plt.show()

The initial plot above gives us an indication of the transit routes with respect to latitudes and longitudes. However, it is very unclear about how the routes correspond to the actual geography of the San Francisco Bay Area. To do so, I plot the routes above, with an underlying map using the “contextily” library.

gp_df_route.crs = "EPSG:4326"
gp_df_route = gp_df_route.to_crs(epsg=3857)
ax = gp_df_route.plot(figsize=(10, 10), alpha=1.0, edgecolor='blue')
ctx.add_basemap(ax, source=ctx.providers.CartoDB.Positron)
plt.show()

The map above looks much better when giving geographical context to the SF Muni Transit routes. I will now use the “SERVICE_CA” and plot the different types of services offered by the SFMTA, using a different color for each type. This involves only a minor modification to the code above, where we now plot by column = “SERVICE_CA” and include a legend to the plot as well.

ax = gp_df_route.plot(column = "SERVICE_CA", legend = True, figsize=(10, 10), alpha=1.0,  legend_kwds={'loc': 'upper left'})
ctx.add_basemap(ax, source=ctx.providers.CartoDB.Positron)
plt.show()

Hope you find this article useful and best wishes for analyzing transit routes across the world! Please leave any thoughts, questions and ideas!

Sources:

  1. Author’s Kaggle Analysis Notebook: https://www.kaggle.com/code/adyg1234/sf-muni-route-stops-visualization-basic-version
  2. SF Open Data Transit Routes Data: https://data.sfgov.org/Transportation/Muni-Simple-Routes/9exe-acju
  3. SFMTA Website: https://www.sfmta.com/

--

--