Step 4: Add some colors¶
In this step, we will prepare and include statistical data and use it to color the municipalities on the map.
Contents
Preparation of statistical data¶
As statistical data, we will use data on municipalities provided by the Swiss Federal Statistical Office. You can download the Excel file and open it, for example using LibreCalc.
Hint
If you want to skip the data preparation steps, you can download the CSV file (right-click, save as ...) from the repository and save it to data/areastatistics.csv
. You can then proceed to the section Select some colors.
Unfortunately, the file is not ready to use as such because the file has some metadata and merged column labels at the top. We want it to start right with one row of data labels followed by the data rows.
Also, the file contains a lot of columns which we will not use. In order to keep file size minimal, we are going to delete all unnecessary columns from the file.
- For our tutorial, we only need the following columns:
- Gemeindecode
- Gemeindename
- Gesamtfläche in km²
- Siedlungsfläche in %
- Landwirtschaftsfläche in %
- Wald und Gehölze in %
- Unproduktive Fläche in %
This means you can do the following actions in the Excel file:
- Delete columns W to AU
- Delete columns R and T
- Delete columns C to O
- We use row 9 as our new header to label the columns:
id
name
area
urban
agriculture
forest
unproductive
- Delete rows 1 to 8
- Delete rows 2354 to 2367
The table should now look like this:
id | name | area | urban | agriculture | forest | unproductive |
---|---|---|---|---|---|---|
1 | Aeugst am Albis | 7.9 | 12.6 | 51.3 | 30.9 | 5.2 |
2 | Affoltern am Albis | 10.6 | 30.8 | 40.1 | 28.2 | 0.9 |
... | ... | ... | ... | ... | ... | ... |
We can now export it as CSV document and save it to our data folder as data/areastatistics.csv
.
When saving it, make sure to use the following settings:
- Character set: Unicode (UTF-8)
- Field delimiter: ,
- Text delimiter: “”
Select some colors¶
Next we are going so select some colors for our map. For this, we are using ColorBrewer, which is great at giving color advice for maps.
We choose 9 data classes and select a color scheme that appeals to us, for example YlGnBu. We then click on “Export” and copy the CSS classes for this scheme.
These CSS classes are now pasted in the CSS style section of our HTML document.
10 11 12 13 14 15 16 17 18 19 20 21 | /* ... */
/* Thanks to http://colorbrewer2.org/ */
.YlGnBu .q0-9{fill:rgb(255,255,217)}
.YlGnBu .q1-9{fill:rgb(237,248,177)}
.YlGnBu .q2-9{fill:rgb(199,233,180)}
.YlGnBu .q3-9{fill:rgb(127,205,187)}
.YlGnBu .q4-9{fill:rgb(65,182,196)}
.YlGnBu .q5-9{fill:rgb(29,145,192)}
.YlGnBu .q6-9{fill:rgb(34,94,168)}
.YlGnBu .q7-9{fill:rgb(37,52,148)}
.YlGnBu .q8-9{fill:rgb(8,29,88)}
|
Color the municipalities by attribute¶
We have selected 9 classes from ColorBrewer so we want to split the attribute values into 9 categories. Each feature then receives a CSS class based on the category of its value and the CSS class will determine its color on the map.
To achieve the categorization, we create a quantize scale with D3. It creates a number of classes within a given domain and we use it to return the class name used by ColorBrewer.
At the same time, we prepare a D3 mapping object called dataById
which will later permit easy access to the data we are about to read. More on that later.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | // ...
// We prepare an object to later have easier access to the data.
var dataById = d3.map();
// We create a quantize scale to categorize the values in 9 groups.
// The domain is static and has a maximum of 100 (based on the
// assumption that no value can be larger than 100%).
// The scale returns text values which can be used for the color CSS
// classes (q0-9, q1-9 ... q8-9)
var quantize = d3.scale.quantize()
.domain([0, 100])
.range(d3.range(9).map(function(i) { return 'q' + i + '-9'; }));
// ...
|
Since the class of the feature depends on the category of the attribute, we need to wait until the CSV is loaded until we can draw the features on the map.
We will load the CSV (using d3.csv()
) inside the function called after loading the GeoJSON. The drawing of the features will now happen inside the function called after the CSV is available, meaning that we replace the existing function and move it inside the d3.csv()
function.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | // ...
// Read the data for the cartogram
d3.csv('data/areastatistics.csv', function(data) {
// This maps the data of the CSV so it can be easily accessed by
// the ID of the municipality, for example: dataById[2196]
dataById = d3.nest()
.key(function(d) { return d.id; })
.rollup(function(d) { return d[0]; })
.map(data);
// We add a <g> element to the SVG element and give it a class to
// style it later. We also add a class name for Colorbrewer.
svg.append('g')
.attr('class', 'features YlGnBu')
// D3 wants us to select the (non-existing) path objects first ...
.selectAll('path')
// ... and then enter the data. For each feature, a <path>
// element is added.
.data(features.features)
.enter().append('path')
.attr('class', function(d) {
// Use the quantized value for the class
return quantize(dataById[d.properties.GMDNR].urban);
})
// As "d" attribute, we set the path of the feature.
.attr('d', path);
});
// ...
|
Play around¶
You can try and change the key of the map which is visualized on the map. You can do this by changing the key accessed by the dataById
object called inside the quantize()
function.
64 65 66 67 68 69 70 71 | // ...
.attr('class', function(d) {
// Use the quantized value for the class
return quantize(dataById[d.properties.GMDNR].urban);
})
// ...
|
Try to set it to agriculture
, forest
or unproductive
and refresh the map.
Next
Proceed to Step 5: Dynamic color domain.
Code¶
- For reference, the file
index.html
after step 4: https://github.com/lvonlanthen/data-map-d3/blob/step-04/index.html
- For reference, the file
- For reference, the file
style.css
after step 4: https://github.com/lvonlanthen/data-map-d3/blob/step-04/style.css
- For reference, the file
- For reference, the file
map.js
after step 4: https://github.com/lvonlanthen/data-map-d3/blob/step-04/map.js
- For reference, the file
- The diff view of step 3 and step 4:
https://github.com/lvonlanthen/data-map-d3/compare/step-03...step-04?diff=split