Thematic maps often use a color ramp based on a single color to show data density. Darker colors show a higher concentration of objects, while lighter colors show lower concentrations. You can use a transparency ramp instead of a color ramp to show density as well. This technique is useful if you want to overlay the density layer on imagery or other vector layers. In this recipe, we'll be using some bear-sighting data to show the concentration of bears over an area. We'll use alpha values to show the density. We'll use an unusual hexagonal grid to divide the area and a rule-based renderer to build the display.
You will need to install the MMQGIS plugin, which is used to build the hexagonal grid using the QGIS Plugin Manager.
You also need to download the bear data from https://geospatialpython.googlecode.com/svn/bear-data.zip, unzip the shapefile, and put it in the ms
directory of your qgis_data
directory.
We will load the bear data. Then, we will use the MMQGIS plugin to generate the hexagonal grid. Then, we'll use the Processing Toolbox to clip the hexagon to the bear shapefile, and join the shapefile attribute data to the hexagon grid. Finally, we'll use a rule-based renderer to apply alpha values based on bear-sighting density and add the result to the map. To do this, we need to perform the following steps:
import processing from PyQt4.QtGui import * from mmqgis import mmqgis_library as mmqgis
dir = "/qgis_data/ms/" source = dir + "bear-data.shp" grid = dir + "grid.shp" clipped_grid = dir + "clipped_grid.shp" output = dir + "ms-bear-sightings.shp"
layer = QgsVectorLayer(source, "bear data", "ogr")
e = layer.extent() llx = e.xMinimum() lly = e.yMinimum() w = e.width() h = e.height()
mmqgis.mmqgis_grid(iface, grid, .1, .1, w, h, llx, lly, "Hexagon (polygon)", False)
processing.runalg("qgis:clip",grid,source,clipped_grid)
processing.runalg("qgis:joinbylocation",source,clipped_grid,0,"sum,mean,min,max,median",0,0,output)
bears = QgsVectorLayer(output, "Bear Sightings", "ogr")
rules = ( ('RARE', '"BEARS" < 5', (227,26,28,255), .2), ('UNCOMMON', '"BEARS" > 5 AND "BEARS" < 15', (227,26,28,255), .4), ('OCCASIONAL', '"BEARS" > 14 AND "BEARS" < 50', (227,26,28,255), .6), ('FREQUENT', '"BEARS" > 50', (227,26,28,255), 1), )
sym_bears = QgsFillSymbolV2.createSimple({"outline_color":"white","outline_width":".26"}) rend_bears = QgsRuleBasedRendererV2(sym_bears) root_rule = rend_bears.rootRule() for label, exp, color, alpha in rules: # create a clone (i.e. a copy) of the default rule rule = root_rule.children()[0].clone() # set the label, exp and color rule.setLabel(label) rule.setFilterExpression(exp) r,g,b,a = color rule.symbol().setColor(QColor(r,g,b,a)) # set the transparency level rule.symbol().setAlpha(alpha) # append the rule to the list of rules root_rule.appendChild(rule)
root_rule.removeChildAt(0)
bears.setRendererV2(rend_bears)
QgsMapLayerRegistry.instance().addMapLayer(bears)
The rule-based renderer forms the core of this recipe. However, the hexagonal grid provides a more interesting way to visualize statistical data. Like a dot-based density map, hexagons are not entirely spatially accurate or precise but make it very easy to understand the overall trend of the data. The interesting feature of hexagons is their centroid, which is equidistant to each of their neighbors, whereas with a square grid, the diagonal neighbors are further away.
This image shows how the resulting map will look: