[GIS] How to calculate raster statistics for polygons

qgisrastersagastatistics

how can I calculate sums, averages etc of raster-points (multi-band) per polygon of a vector-layer. I was told that this is called "zonal statistics". I tried that with QGIS first.

There is a way to do it but that is much too slow (convert raster to vector, intersect with second vector-layer, calculate geometry, export numbers, calculate statistics with spreadsheet or other program, re-import the results, takes forever for my 350.000 raster-points).

I was also given the hint to use saga-gis. That has "zonal statistics" but those are based on categories from a raster-band, not on polygons from a vector-layer. So to use this I would have to convert my vector-layer to raster and then calculate the statistics.

This seems to be the wrong way to solve this. There would be no way to account for raster-points that belong to 2 or more polygons because they are intersected by the polygon-boundary. I assume that polygon-based statistics should be able to handle this so I also assume that I haven't found the correct module yet.

Saga-gis has really many modules. Please let me know which one is the right one for this application.

Best Answer

I was struggling to do exactly the same thing, but for various reasons I'm committed to using QGIS. I tried using v.rast.stats using the GRASS plugin and also via the Sextante plugin. The latter approach failed, because it seems to attach the stats to a temporary vector layer which it then deletes. The GRASS plugin worked, but it doesn't deal with overlapping polygons.

After doing some digging around (in the source of the promising-sounding ZonalStats plugin), I found that QGIS actually has zonal statistics methods built into the API, and these also have Python bindings. So as long as you are only looking for count, sum and mean statistics for your polygon features, the Python Console (Plugins > Python Console) is currently the easiest way to attach the stats to the polygon attribute table.

  1. Select your raster layer in the TOC, and type the following into the console (it grabs the source file name of your raster layer)

    >>> rasterfile = qgis.utils.iface.mapCanvas().currentLayer().source()

  2. Select your vector layer, and execute the following command in the console (it grabs the vector layer itself)

    >>> vectorlayer = qgis.utils.iface.mapCanvas().currentLayer()

  3. Execute the following three commands in the console (they pass the vector layer and raster file to QGIS' built-in zonal stats calculator)

    >>> import qgis.analysis

    >>> zonalstats = qgis.analysis.QgsZonalStatistics(vectorlayer,rasterfile)

    >>> zonalstats.calculateStatistics(None)

The results will be appended as extra fields in the polygon layer.

Zonal Statistics

Note that if you want to append a prefix to the new fields (rather than just having them as sum, mean and count), then you would replace the first command in step 3 with the following (assuming you wanted to use 'zonal_' as the prefix:

>>> zonalstats = qgis.analysis.QgsZonalStatistics(vectorlayer,rasterfile,"zonal_")