0

Is it possible to make one attribute table using zonal statistics for one vector and multiple rasters layers?

I would like to make chart for one field with five sectors (polygons) in that field and show NDVI values per five years (about seventy rasters)/per that five sectors.

2 Answers 2

1

One option is to use the batch mode of zonal statistics. To activate it, click on the Run as batch process button at the bottom-left corner of the zonal statistics window.

There you can either manually specify the required info or even better you can create a json that includes all the necessary info and then load it using the following icon:

enter image description here

The json should be structured like this:

[
    {
        "PARAMETERS": {
            "INPUT": "'C:/Users/user/plgn_in.shp'",
            "INPUT_RASTER": "'C:/Users/user/raster_1.tif'",
            "RASTER_BAND": "1",
            "COLUMN_PREFIX": "'_'",
            "STATISTICS": "[0,1,2]"},
            "OUTPUTS": {
                "OUTPUT": "C:/Users/user/plgn_1_out.gpkg"
            }
    },
    {
        "PARAMETERS": {
            "INPUT": "'C:/Users/user/plgn_in.shp'",
            "INPUT_RASTER": "'C:/Users/user/raster_2.tif'",
            "RASTER_BAND": "3",
            "COLUMN_PREFIX": "'_'",
            "STATISTICS": "[1,2]"},
            "OUTPUTS": {
                "OUTPUT": "C:/Users/user/plgn_2_out.gpkg"
            }
    }
]
2
  • I've try batch process, but it makes one table for every raster. After that i must manualy merge columns to one table to make chart. I need zonal statistics of diferent rasters in one table. Commented Jul 8, 2023 at 16:38
  • You can join the resulting polygons at the end. As far as I know, you cannot do what you want in a single step.
    – pan
    Commented Jul 8, 2023 at 18:05
0

You can use Python.

Add all NDVI raster layers to the map and your polygon layer defining the zones.

For this to work your NDVI layers have to have ndvi or NDVI in the layer name and the year as four digits, for example ndvi_2015. Or you will have to modify the code.

Output will be a temp layer with each years mean NDVI values as columns:

import re
vector_layer = QgsProject.instance().mapLayersByName("polygonlayer")[0] #The polygon layer to use as zones. Change "polygonlayer" to the name of your layer

#List NDVI layers added to the map
ndvi_list = [] #A list to store the raster layers 
for layer in QgsProject.instance().mapLayers().values():
    if "ndvi" in layer.name().lower(): #If the layer name contains ndvi/NDVI
        ndvi_list.append(layer) #Append the layer to ndvi_list
print(ndvi_list)
#[<QgsRasterLayer: 'NDVI_2015' (gdal)>, <QgsRasterLayer: 'NDVI_2020' (gdal)>]

#Sort the list from oldest to newest
pattern = r"\d{4}" #Exactly four digits
re.search(pattern=pattern, string=ndvi_list[0].name()).group(0)
ndvi_list.sort(key=lambda x: int(re.search(pattern=pattern, string=x.name()).group(0))) #Sort the ndvi layers from oldest to newest


#For each nvdi layer in the list, execute zonal statistics using the previous output layer as input
for e, ndvi in enumerate(ndvi_list, 1):
    year=re.search(pattern=pattern, string=ndvi.name()).group(0) #Extract the year to use to name the columns
    if e==1: #If it is the first raster being processed, use polygon layer as zones
        zonstats = processing.run("native:zonalstatisticsfb", {'INPUT':vector_layer,
            'INPUT_RASTER':ndvi,'RASTER_BAND':1,'COLUMN_PREFIX':f"{year}_",'STATISTICS':[2],
                'OUTPUT':'TEMPORARY_OUTPUT'})["OUTPUT"]
    else: #For all other years, use the last zonal stats output as input
        zonstats = processing.run("native:zonalstatisticsfb", {'INPUT':zonstats,
            'INPUT_RASTER':ndvi,'RASTER_BAND':1,'COLUMN_PREFIX':f"{year}_",'STATISTICS':[2],
                'OUTPUT':'TEMPORARY_OUTPUT'})["OUTPUT"]

QgsProject.instance().addMapLayer(zonstats) #Add the result to the map

I only have two years and they have the same NDVI values:

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.