Choropleth mapping of half-million buildings in Philadelphia using Mapbox

Xiaojiang Li
7 min readNov 2, 2020

--

When you start web mapping, you may use Leaflet and geojson to create your first web-based geovisualization. However, if you try to visualize more geographical features, like tens of thousands or even more features, you may find your web map becomes very slow as your geojson becomes much larger. Using Mapbox Tilling, you can visualize hundreds of thousands of features efficiently. Here is an example to create a choropleth map of about 500,000 building blocks in Philadelphia using Mapbox.

  1. Data preparation

The building footprint map and parcel-level land use map can be downloaded from Pennsylvania Spatial Data Access (Link). Fig 1. shows the building footprint map in Philadelphia.

Fig. 1. The building footprint map of Philadelphia, there are more than 500,000 building blocks in Philadelphia

In order to get the land-use type of each building block, I used Python + R-Tree to do the intersection of the building footprint map and the land use map to assign the land use type for each building block. If you don’t want to do the intersection yourself, you can download the dataset from here. Fig. 2 shows the overlay of the land use map and building footprint map in a small region of Philadelphia.

Fig. 2. The overlay of the land use map and the building footprint map in part Philadelphia

After the intersection, the new building footprint map will have land-use information with a size of 125M. In order to visualize those building blocks on the web, we need to convert the shapefile into geojson a file. There are many tools available to do the conversion. You can use GDAL the command to do that, type the following command in your anaconda prompt,

ogr2ogr -f GeoJSON -t_srs crs:84 buildings_ft.geojson building_ft_lu.shp

Note: Make sure the building_ft_lu.shp file is in your working directory.

If you don’t like to use the commands, you can use QGIS to do the conversion,

You will find the generated geojson file is about 500M, much larger than your original shapefile and it is way beyond the upload limit of a geojson file in Mapbox Studio.

You can convert the geojson file into mbtiles file using the tool of Tippecanoe. Type in the following command to do the conversion if you have Tippecanoe installed.

tippecanoe -ac -an -y landuse -l buildings -A “© Building land use types by Xiaojiang Li” -o buildings.mbtiles buildings.geojson

Here are some details about different parameters,

1. -y to remove all metadata except for the landuse field.

2. -ac to coalesce adjacent features with the same property (in this case, matching only landuse since that’s all we keep). Coalescing will have the effect of only allowing identical styling between these coalesced features, but since I just want to style based on land use type, this doesn’t really matter.

3. -an to drop the physically smallest features in order to keep tile sizes within reasonable limits. For lower-zoom tiles which show many buildings at once, this won’t be noticeable visibly.

If you don’t have the Tippecanoe installed, you can install it easily. On Mac OS, the easiest way to install tippecanoe on OSX is with Homebrew:

$ brew install tippecanoe

On Ubuntu it will usually be easiest to build from the source repository:

git clone https://github.com/mapbox/tippecanoe.git
cd tippecanoe
make -j
make install

The Tippecanoe is only available on Mac and Linux. If you are on Windows, you can use a Linux virtual machine or try to use a cloud computing environment.

You new mbtiles file is much smaller, with a size of 15M. This is much smaller than 500M or 150M. Now, we are done with the data preparation and are ready for the geovisualization part. I provide the mbtiles file here, if you are not able to do the conversion yourself.

2. Upload to Mapbox Studio and style your map

If you don’t have a Mapbox account, you need to register one for the following steps. Go to studio.mapbox.com to register your account.

Fig. Mapbox account register

Then click the Tileset the menu on the top right of your page, and then click the New tileset to upload your mbtiles file.

After uploading your mbfiles, then you can style your map in Mapbox studio. Click the Style on the top right of your web page to create a new Style. Select one template as the basemap,

In my case, I select one dark basemap,

Click the layer on the top left of your styling page and add a new layer and find the id of your uploaded mbtiles file. Then you can style your data layer, assign different land-use types as different colors.

When everything is done, then you can publish your data layer,

3. Let Mapbox Studio and Mapbox GL JS work together

Now let write code to create our web-map. Let’s first create a blank HTML page,

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Display a map</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.css" rel="stylesheet" />
<style>
body {
margin: 0;
padding: 0;
}
h2,
h3 {
margin: 10px;
font-size: 1.2em;
}
h3 {
font-size: 1em;
}
p {
font-size: 0.85em;
margin: 10px;
text-align: left;
}
.map-overlay {
position: absolute;
bottom: 0;
right: 0;
background: rgba(255, 255, 255, 0.8);
margin-right: 20px;
font-family: Arial, sans-serif;
overflow: auto;
border-radius: 3px;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
#features {
top: 0;
height: 100px;
margin-top: 20px;
width: 250px;
}
#legend {
padding: 10px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
line-height: 18px;
height: 150px;
margin-bottom: 40px;
width: 100px;
}
.legend-key {
display: inline-block;
border-radius: 20%;
width: 10px;
height: 10px;
margin-right: 5px;
}
</style>
</head>
<body>
<div id="map"></div>
<div class="map-overlay" id="features">
<h2>Building footprint map</h2>
<div id="pd"><p>The building id is</p></div>
</div>
<div class="map-overlay" id="legend"></div>
<script></script></body>
</html>

We are going to write JavaScript code and add map elements. First, add your Mapbox token and map instance,

// put you token here
mapboxgl.accessToken = 'your-token';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://your-style-url',
zoom: 10,
center: [-75.150996, 39.992945]
});

Using your Mapbox Studio URL to replace the above mapbox://url. You can find your URL by clicking sharing on the top right of the Mapbox studio.

You can then open your .html file and check your web page.

Adding the following code to add a legend to your map,

// add legend to your map
var layers = ['Commercial land', 'Residential land', 'Institutional land', 'Other'];
var colors = ['#bf0808', '#32f145', '#e9f54d', '#000000'];
for (i = 0; i < layers.length; i++) {
var layer = layers[i];
var color = colors[i];
var item = document.createElement('div');
var key = document.createElement('span');
key.className = 'legend-key';
key.style.backgroundColor = color;
var value = document.createElement('span');
value.innerHTML = layer;
item.appendChild(key);
item.appendChild(value);
legend.appendChild(item);
}

Add information window, when the cursor is hovering over a building block, the building land use information will show up.

map.on('load', function() {
map.getCanvas().style.cursor = 'default';
map.fitBounds([
[-75.299998, 40.091772],
[-75.011607, 39.884492]
]);

// change info window on hover
map.on('mousemove', function(e) {
var states = map.queryRenderedFeatures(e.point, {
layers: ['buildings-lu-new'] // get from the mapbox top left layer information
});

if (states.length > 0) {
document.getElementById('pd').innerHTML =
'<h3><strong> building id:' +
// states[0].properties.fid +
'</strong></h3><p><strong><em>' +
states[0].properties.landuse;
} else {
document.getElementById('pd').innerHTML =
'<p>The building id is: </p>';
}
});
});

Reference

Make choropleth maps using Mapbox, https://docs.mapbox.com/help/tutorials/choropleth-studio-gl-pt-1/

Visualzing building footprint using Mapbox, https://blog.mapbox.com/visualizing-an-entire-citys-buildings-live-with-runtime-styling-453fe7e39ae6

--

--

Xiaojiang Li

Spatial Data Scientist, Urban Scientists, Prof at UPenn, Founder of Biomteors, Alum of MIT Senseable, http://www.urbanspatial.info, http://www.biometeors.com