Learn to create map visualizations and apply colormaps.


There are three parts to the assignment. You may complete the assignment in a single HTML file or use multiple files (e.g. one for CSS, one for HTML, and one for JavaScript). You must use D3 v4 for this assignment. All visualization should be done using D3 calls. You may use other libraries (e.g. underscore.js or jQuery), but you must credit them in the HTML file you turn in. Extensive documentation for D3 is available, and Vadim Ogievetsky's example-based introduction that we went through in class is also a useful reference. In addition, Scott Murray's Interactive Data Visualization for the Web is a good reference.

Due Date

The assignment is due at 11:59pm on Thursday, March 29.


You should submit any files required for this assignment on myCourses. You may complete the assignment in a single HTML file or use multiple files (e.g. one for HTML, one for CSS, and one for JavaScript). Note that the files should be linked to the main HTML document accordingly. The filename of the main HTML document should be a3.html. myCourses may complain about the files; if so, please zip the files and submit the zip file instead.


In this assignment, we will examine Massachusetts school district per-pupil spending data. This data is compiled by the Commonwealth's Department of Education, and the raw data is available on their web site. I have extracted this data to a CSV. In addition, the Commonwealth makes the geographic boundaries of the school districts available as a Shapefile. I have converted this data to GeoJSON files that D3 can more easily handle. In addition, the boundaries have been simplified. The 100m version (below) should work fine, but if it is slow, you may change to the 500m version which is smaller and has more simplified geometry (use only one!). The goal of the assignment is to understand per-pupil spending by district and examine any spatial trends.

0. Info

Like Assignment 1, start by creating an HTML web page with the title "Assignment 3". It should contain the following text:

  • Your name
  • Your student id
  • The course title ("Data Visualization (DSC 530/CIS 602-01)"), and
  • The assignment title ("Assignment 3")
  • The text "This assignment is all my own work. I did not copy the code from any other source." (Your inclusion of this text indicates that you understand the consequences of violating the UMass Dartmouth Student Academic Integrity Policy.)

If you used any additional JavaScript libraries or code references, please append a note to this section indicating their usage to the text above (e.g. "I used the jQuery library to write callback functions.") Include links to the projects used. You do not need to adhere to any particular style for this text, but I would suggest using headings to separate the sections of the assignment.

A template for the assignment is provided: html, js; save them both as source. You may use this or create your own files.

1. MA District Map (30 pts)

Create a map that shows the school district boundaries. Note: Some boundaries will overlap because certain regions have local schools as well as regional or vocational schools. For this part of the assignment, each district should have the same color; use a lower opacity to show where overlaps occur. You will only need the GeoJSON data for this part of the assignment.

Remember that you will need a projection for the map. For this assignment, we will use the Massachusetts State Plane projection. This is a version of D3's Conformal Conic Projection. You will need to set the parallels and rotate settings as defined by the State Plane projection. (Note that for rotation, the signs are flipped.)

For the map, you will want to use each district as a separate feature. Thus, you should use mapData.features with the normal selection plus data binding. Each feature will have an id attribute that can be used with the counts to derive the fill color. You can load the mapData via d3.json. Note that this is an asynchronous call, and you should provide a callback function that is executed only after the data is loaded. Thus, all code that depends on the data must reside or be called from that callback function.

Example Solution for Part 1

Example Solution for Part 1


  • Each district is a feature so if mapData is the variable loaded by d3.json, mapData.features is a list of all of the school districts.
  • d3.geoPath can have an associated projection is used to translate GeoJSON features into paths on screen.

2. MA District Per-Pupil Spending (40 pts)

Create two new choropleth maps that show the total per-pupil spending, one for local public ("Local Public", [0,399]) schools and one for regional public schools ("Regional Academic", [600,799]). The colormap should be the same for both visualizations so that the values are comparable. Create a legend so a viewer can understand the values. Since we are drawing two similar maps, create one function that will draw a map and has parameters for the divId, mapType, etc. that can be called for both maps. You will points if you do not have such a reusable function.

You will need to match the data in the GeoJSON file with the data in the spending csv file. Characters 1-3 of ORG_CODE property can be linked to the LEA field for each spending object, or the DISTRICT property can be linked to the District field in the spending object. Given a GeoJSON feature f, the ORG_CODE (DISTRICT) is accessed from the properties object as f.properties.ORG_CODE (f.properties.DISTRICT). For each one of the maps, you will need to filter the schools based on the appropriate type. Districts with LEA codes in the [0, 399] range have a "Local School" type while districts with LEA codes in the [600,799] range have a "Regional Academic" type. The type is also encoded in the GeoJSON file as the MADISTTYPE property.

Per-pupil data is stored in the TTPP field of each object in the spendingData array. You should use a sequential color scale to visualize this data.

Finally, to load multiple external data files using D3, use the queue library by Mike Bostock. This is part of the default D3 v4 bundle so you do not need to add another JavaScript libraries (as you did with D3 v3) Then, to load a JSON files file1.json and a CSV file file2.csv, you would have the following code:

function processData(errors, file1data, file2data) {
    // code

    .defer(d3.json, "http://example.com/path/to/file1.json")
    .defer(d3.csv, "http://example.com/path/to/file2.csv")


  • If you craft your function to create the map in Part 1 well, you can use reuse that function and just update the fill (and reset the opacity) based on the spending data.
  • d3.scaleSequential can help with colormapping. Remember to check the type of the values you are displaying to determine a correct colormap.
  • To create a good colormap, make sure to get the extent of the data. Also, when data is missing/undefined, use a fill that indicates this (e.g. "none")

3. MA District Spending Overlay (30 points)

While these maps are useful if you are familiar with Massachusetts geography, it can be difficult to tell which towns are covered by a particular regional district. Web mapping technologies (e.g. Leaflet, MapboxGL) can display features like towns, highways, parks, etc., using map tiles. We can use D3 to overlay the school district information on top of such maps so that we can explore the district boundaries and trends in relationship to other features. (Note that it is also possible to create choropleth layers using routines in these libraries without D3, but we will focus on D3 overlays in the assignment.) You may choose to use either Leaflet or MapboxGL for the assignment; you only need to use one. Both are open-source but MapboxGL requires a developer access token. To use Mapbox, you need to sign up for a free account that will provide you with a token that allows 50,000 map views per month. This should be sufficient for your work on this assignment. Sign up for an account. Your token is visible here in your account here. You should use the regional districts as the overlay.

We will still create an SVG, but this SVG will sit on top of the map from Leaflet or MapboxGL. You will need to create an SVG for the overlay. In Leaflet, you can use the built-in overlay pane (map.getPanes().overlayPane), and in MapboxGL, you can add the svg to the canvas container (map.getCanvasContainer()). We will update D3's paths when a user moves or zooms in on the map. This is done using a point geoTransform that uses the underlying map's projection information. Here is some example code based on Mike Bostock's work assuming map is the existing map object:

    function projectPoint(lng, lat) {
        let point = map.latLngToLayerPoint(new L.LatLng(lat, lng));
        this.stream.point(point.x, point.y);

    transform = d3.geoTransform({point:projectPoint});
    path = d3.geoPath().projection(transform);

For MapboxGL, replace the second line with

        let point = map.project(new mapboxgl.LngLat(lng, lat));

Note that the order of latitude and longitude is swapped!. Then, projectPoint must be called whenever the map view is changed (generally, the viewreset, move, and movestart events).

Example Solution for Part 3

Example Solution for Part 3


  • Draw a standard Leaflet or MapboxGL map first and then figure out how to add the overlay
  • For both libraries, include the CSS stylesheets: Leaflet, MapboxGL.
  • In Leaflet, latitude is first, in MapboxGL, longitude is first.
  • Set the position: absolute CSS rule for the svg layer and use z-index style to position the svg over the map
  • The event .on(...) callbacks take the name of the event and a callback function. The callback function need only recreate each path's d attribute (a single line of code).

Extra Credit

Either of the following will qualify for extra credit:

  • Create a new version of Part 1 that differentiate the district types. This map shows an attempt at doing this.
  • Implement the ability to show/hide layers in Part 3 so a user can toggle between "Local Schools" and "Regional Academic" (or more) districts.