A proportional symbol map puts a circle on each place and makes the circle bigger when the number is bigger. It is the simplest honest way to show totals on a map, and it is easy to get subtly wrong: scale the radius instead of the area and every large value looks far larger than it is.
This guide covers how to size the symbols, graduated versus proportional symbols, and how to build one with MapLibre, using enforcement camera counts from our own dataset.
What a proportional symbol map is
A proportional symbol map is a thematic map in which each location gets a symbol whose size represents a quantity measured at that location.
Three things define one:
- The anchor point. Where the symbol sits: a real coordinate, such as a store or a city, or the centroid of a region, such as a country.
- The value. One count per anchor: people, sales, visits, cameras.
- The scaling rule. How a value turns into a symbol size, which decides whether the map is accurate.
The earliest clear attempt at proportional point sizes is usually credited to Henry Drury Harness, on an 1838 map of cargo traffic in Ireland. Circles are the usual shape because they are compact, they have no orientation, and their area is easy to compute.
The term bubble map is sometimes used for the same thing, particularly in charting tools.
Scale the area, not the radius
A reader judges a circle by how much ink it covers, which is its area. Area grows with the square of the radius. So the rule is:
- Area proportional to value. A place with four times the count gets four times the area.
- Radius proportional to the square root of the value. Four times the count means twice the radius.
Set the radius directly from the value instead, and four times the count gets sixteen times the area. The figure shows the effect on the ten countries with the most cameras in our dataset.
In the top row, radius tracks the count, and Poland almost disappears next to Italy even though it has about one twelfth of Italy's cameras (875 against 10,707). In the middle row, area tracks the count, and the United Kingdom's circle covers 54 percent of Italy's, which matches 5,806 against 10,707.
The Flannery correction
Square-root scaling is mathematically correct and still slightly misread. James Flannery's experiments on how people judge circle sizes, published in 1971, found that readers consistently underestimate how much larger a big circle is than a small one.
The correction usually attributed to his work replaces the exponent 0.5 with 0.5716, so the radius is (value / maxValue) ^ 0.5716 times the largest radius. Large circles come out slightly larger than strict proportionality, offsetting the underestimate. If you use it, say so in the caption. For most web maps, plain square-root scaling plus a good legend is the better default, because the encoding stays exact and explainable.
Graduated vs proportional symbols
The two terms overlap, and the overlap causes most of the confusion around this topic.
Proportional (unclassed) symbols size every symbol directly from its value. Every difference is preserved, although readers still struggle to read exact numbers off the circles.
Graduated (classed) symbols first sort the values into a small number of classes, as a choropleth map does, then give every place in a class the same symbol. The bottom row of the figure above uses four classes: under 1,000, 1,000 or more, 2,500 or more, and 5,000 or more. Italy and the United Kingdom get the same circle, although Italy has 1.8 times as many cameras.
The Axis Maps thematic cartography guide sums up the trade: classing loses detail and produces fewer map reading errors, because a reader only has to match a circle to one of three or four legend sizes.
Use proportional symbols when the exact spread of values is the story, or when readers can hover for the number. Use graduated symbols for print, for small screens, and when the reader needs to say which group a place is in.
In AP Human Geography and many textbooks, graduated symbol map is simply another name for a proportional symbol map. In GIS software the two words usually name two different renderers: graduated means classed, proportional means unclassed. Check which one your audience means.
When to use it instead of a choropleth
The test is the same one that separates every thematic map type: is the number a total or a rate?
- Totals go on symbols. Cameras per country, customers per store, passengers per station. Symbol size scales with the count, and region area plays no part.
- Rates go on a choropleth map. Cameras per 10,000 km², customers per 1,000 residents. Colour carries the rate, and region area is normalised away.
A choropleth of raw counts is the classic mistake, because large regions look important simply because they are large. A proportional symbol map avoids that bias without distorting the geography, unlike a cartogram, and needs no dot value or placement rule, unlike a dot density map. The thematic map guide covers the whole family.
A worked example: enforcement cameras in Europe
Here is the format on our own data. The MapAtlas Camera Index is a crowd-sourced record of speed, red light, average speed, and variable limit cameras, published under CC BY 4.0 from a 2024-05-21 snapshot. The map shows the same 40 European countries as the cartogram article, each with one circle at its centroid, sized by cameras recorded.
| Country | Cameras in the index | Share of the 40 countries | Circle area vs Italy | Circle radius vs Italy |
|---|---|---|---|---|
| Italy | 10,707 | 25.0% | 100% | 100% |
| United Kingdom | 5,806 | 13.6% | 54.2% | 73.6% |
| Germany | 4,714 | 11.0% | 44.0% | 66.4% |
| France | 3,853 | 9.0% | 36.0% | 60.0% |
| Belgium | 2,701 | 6.3% | 25.2% | 50.2% |
| Sweden | 2,455 | 5.7% | 22.9% | 47.9% |
| Spain | 2,104 | 4.9% | 19.7% | 44.3% |
| Austria | 1,457 | 3.4% | 13.6% | 36.9% |
| Finland | 1,089 | 2.5% | 10.2% | 31.9% |
| Poland | 875 | 2.0% | 8.2% | 28.6% |
The last two columns are the scaling rule in numbers. Belgium has a quarter of Italy's cameras, so its circle has a quarter of the area and half the radius.
Three things stand out. Four countries, Italy, the United Kingdom, Germany, and France, hold 25,080 of the 42,762 cameras plotted, 58.7 percent. Belgium draws the fifth largest circle on one of the smaller countries in the frame; on a choropleth of counts, its dark fill would cover almost none of the image. And most of eastern Europe shows small circles: Ukraine, the largest country in the frame, has 348.
Method. Counts are aggregate totals per country from the index catalogue; no camera coordinates are used. Circles sit at a fixed centroid per country with area proportional to the count. Five countries with fewer than 15 cameras (San Marino, Ireland, Monaco, North Macedonia, Liechtenstein) are drawn at a 1.2 pixel minimum so they stay visible. Russia and Turkey are left out because their centroids fall outside a European frame. The 40 countries hold 42,762 of the 106,646 cameras in the index, which covers 106 regions worldwide.
The index is built from driver reports, so a small circle can mean light enforcement or light reporting, and this data cannot separate the two. Treat very small counts, such as Ireland with 6 cameras and Denmark with 20, as a question about coverage rather than an answer about enforcement. The enforcement camera article compares the index against OpenStreetMap for the countries where that is possible.
Overlap, drawing order, and legends
Let some circles overlap. Symbols large enough to read will collide in dense areas such as the Benelux. The usual rule of thumb: some overlap is fine as long as the centre of most symbols stays visible. Shrinking everything until nothing touches makes small values unreadable.
Draw the largest circles first. Smaller symbols then sit on top of larger ones, where they hide less. Keep a thin white outline and some transparency so the edge of the circle underneath stays visible.
Use a nested legend. Two or three reference circles with round values, sharing a bottom edge, let readers calibrate by eye. Pick values inside the range of your data, such as 1,000, 5,000 and 10,000 here. The map legend guide covers the layout.
Label or expose the number. Area is hard to read precisely, so label the largest symbols and put the exact value in a tooltip or a table next to the map.
How to build one with MapLibre
The data is a GeoJSON point source: one feature per place, with the count as a property. For countries, the point is a centroid or a hand-placed label point.
const countries = {
type: 'FeatureCollection',
features: [
{ type: 'Feature', geometry: { type: 'Point', coordinates: [12.6, 42.8] }, properties: { name: 'Italy', cameras: 10707 } },
{ type: 'Feature', geometry: { type: 'Point', coordinates: [-2.5, 54.0] }, properties: { name: 'United Kingdom', cameras: 5806 } },
{ type: 'Feature', geometry: { type: 'Point', coordinates: [10.4, 51.2] }, properties: { name: 'Germany', cameras: 4714 } },
// ...one feature per country
],
};
const MAX_VALUE = 10707; // largest count in the data
const MAX_RADIUS = 36; // radius in pixels for that count at zoom 3
const map = new maplibregl.Map({
container: 'map',
style: 'https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_STYLE_ID/style.json&token=YOUR_API_KEY',
center: [12, 51],
zoom: 3,
});
map.on('load', () => {
map.addSource('countries', { type: 'geojson', data: countries });
map.addLayer({
id: 'proportional-symbols',
type: 'circle',
source: 'countries',
layout: {
// Higher sort keys draw on top, so negate the count: small circles end up above large ones.
'circle-sort-key': ['-', ['get', 'cameras']],
},
paint: {
// Area proportional to the count: interpolate linearly on the square root of the value.
// The outer zoom interpolation grows every symbol together as the reader zooms in.
'circle-radius': [
'interpolate', ['linear'], ['zoom'],
3, ['interpolate', ['linear'], ['sqrt', ['get', 'cameras']], 0, 0, Math.sqrt(MAX_VALUE), MAX_RADIUS],
6, ['interpolate', ['linear'], ['sqrt', ['get', 'cameras']], 0, 0, Math.sqrt(MAX_VALUE), MAX_RADIUS * 2.5],
],
'circle-color': '#0958a8',
'circle-opacity': 0.72,
'circle-stroke-color': '#ffffff',
'circle-stroke-width': 1,
},
});
});
Three notes on that layer. The inner interpolate maps the square root of the count linearly onto the radius, which is exactly the area rule. circle-sort-key handles drawing order without pre-sorting the data; the MapLibre style specification defines it as higher keys drawing on top. And for the Flannery correction, replace ['sqrt', ['get', 'cameras']] with ['^', ['get', 'cameras'], 0.5716] and the upper stop with MAX_VALUE ** 0.5716.
For graduated symbols, swap the inner expression for a step on the raw count, with one fixed radius per class. The legend is ordinary HTML next to the map: draw the nested reference circles with the same formula so they match the layer.
Where MapAtlas fits
Most of the work in a proportional symbol map goes into clean anchor points and counts keyed to the same identifiers. The Dynamic Maps API serves the base map and country, region, and postal code boundaries as EU-hosted vector tiles, and the GeoEnrich API returns per-region aggregates on the same identifiers, so the counts behind each circle come from one source. For rates rather than totals, start with the choropleth map guide.
Frequently Asked Questions
What is a proportional symbol map?
A proportional symbol map is a thematic map that places a symbol, usually a circle, at each location and sizes it by a value measured there. The area of the symbol is proportional to the value, so a place with twice the count gets a circle with twice the area. It is the standard way to map totals such as population per city, sales per store, or cameras per country.
What is the difference between a graduated symbol map and a proportional symbol map?
In a proportional (unclassed) symbol map every value gets its own symbol size, calculated directly from the number. In a graduated (classed) symbol map the values are first grouped into a few classes, such as under 1,000, 1,000 to 2,499 and 2,500 or more, and every place in a class gets the same symbol. Graduated symbols are easier to match against a legend; proportional symbols keep the exact differences. Many textbooks and AP Human Geography materials use graduated symbol map as a synonym for proportional symbol map, while GIS software usually treats them as two separate renderers.
What are the advantages and disadvantages of a proportional symbol map?
The advantages: it shows totals honestly, it is not distorted by the size of the region the value belongs to, and it lets readers compare two places directly. The disadvantages: readers underestimate differences in circle area, large symbols overlap and hide their neighbours in dense areas, and exact values are hard to read without a legend or labels. It also suits counts only; a rate such as cameras per square kilometre belongs on a choropleth map.
How do you make a proportional symbol map?
You need one point per place (a coordinate or a region centroid), one numeric count per point, and a rule for sizing the symbol. Set the radius to the square root of the value times a scale factor so that circle area carries the number, draw the largest circles first so smaller ones stay visible, and add a legend with two or three nested reference circles. On a web map, a GeoJSON point source with a MapLibre circle layer and a square-root circle-radius expression does the whole job.
