3

I would like to generate a tool that reclassifies rasters in 10 classes with equal intervals. Since QGIS reclassifies tools does not allow to automatically create classes with such methods, I was wondering if I could do it myself inside the graphical modeller this way:

  • Extract the min and the max of a given raster
  • Divide the range of those values in ten breaks
  • Use those breaks to generate a reclassification table
  • Import that reclassification table inside the reclassify tool.

I know that the last step is possible, but I'm not sure about the other ones... Can we process data and informations like this inside the graphical modeller? I know it's possible with Python but for a teaching purpose, I would like to know if it's possible with the graphical modeller specifically.

1
  • Basically yes: You need a model with raster layer statistics to read min and max and reclassify by table tool. However, you'd need a quite complex expression for reclassification: an array such as array(@minfirstclass,@maxfirstclass,@firstclassval,@minsecondclass,@maxsecondclass,@secondclassval,...). You can easily get the breaks with something like generate_series(@rmin,@rmax,(@rmax-@rmin)/9), but the hard part is to stitch the final array together... – MrXsquared Feb 4 at 13:41
1

I have created a model you can download here from my github repo.

Thats how it looks:

enter image description here

Where:

  • r is the input raster
  • NClasses is a numerical input greater 0 (the amount of classes you wish to have)

And:

  • you need to set a dependency for "Reclassy by table", because "Raster layer statistics" needs to execute first
  • you need to insert a rather complex expression to "Reclassify by table", see below

enter image description here

The Expression as explanation (uses different variables than in the actual model above, better to explain this way):

-- CREATE VARIABLES
with_variable('rmin',1,( -- Equals to result of Raster layer statistics MIN result
with_variable('rmax',100,( -- Equals to result of Raster layer statistics MAX result
with_variable('nclasses',10, -- Equals to model input NClasses
-- for copy paste into your own model, only copy below, and change variables

-- NEST ARRAYS
array_to_string(array_foreach( 

-- ADD LOWER CLASS VALUES
array_remove_at(generate_series(@rmin,@rmax,(@rmax-@rmin)/@nclasses),@nclasses)
,@element

-- ADD UPPER CLASS VALUES
-- concat
||','||
-- array of upper classes
array_get(
array_filter(
array_foreach(
generate_series(@rmin,@rmax,(@rmax-@rmin)/@nclasses)
,
array_get(generate_series(@rmin,@rmax,(@rmax-@rmin)/@nclasses),
array_find(generate_series(@rmin,@rmax,(@rmax-@rmin)/@nclasses),@element)+1)
),@element is not null)
,
-- get the index of initial array to insert at this position
array_find(
array_remove_at(generate_series(@rmin,@rmax,(@rmax-@rmin)/@nclasses),@nclasses)
,@element))

-- ADD CATEGORY VALUES
-- concat
||','||
-- array of class values
array_get(generate_series(1,@nclasses),
-- get the index of initial array to insert at this position
array_find(
array_remove_at(generate_series(@rmin,@rmax,(@rmax-@rmin)/@nclasses),@nclasses)
,@element))

)) -- closing array nesting

-- for copy paste into your own model, only copy above, and change variables
))))) -- closing with variable

*Only tested in QGIS 3.16.1


Further explanation on the expression:

The expression basically consists of four parts:

  1. Nest the three arrays below together, to get one single array_to_string like: lowerclass1value,upperclass1value,class1reclassvalue,lowerclass2value,upperclass2value,class2reclassvalue,...
  2. An array to get the lower borders for each class
  3. An array to get the upper borders for each class
  4. An array to get the new values for each new class

#1 is done by:

array_to_string(array_foreach(...),THE_THREE_ARRAYS)

just some complicated nesting, I cant really explain...

#2 is done by:

array_remove_at(generate_series(@rmin,@rmax,(@rmax-@rmin)/@nclasses),@nclasses),@element

Generating a series from raster min value to raster max value in steps by raster range devided by nclasses-1. This will result in n equal classes. Since we only want the lower borders, we remove the last entry (raster max) from the array. The last @element is for nesting.

#3 is done by:

array_filter(
array_foreach(
generate_series(@rmin,@rmax,(@rmax-@rmin)/@nclasses)
,
array_get(generate_series(@rmin,@rmax,(@rmax-@rmin)/@nclasses),
array_find(generate_series(@rmin,@rmax,(@rmax-@rmin)/@nclasses),@element)+1)
),@element is not null)

Generating a series from raster min value to raster max value in steps by raster range devided by nclasses-1. This will result in n equal classes. Since we only want the upper borders here, we remove the first entry (raster min) from the array.

#4 is done by:

generate_series(1,@nclasses)

To generate class values from 1 to the maximum of classes. Step 1.

Cant really explain better.... Maybe best to try out yourself and stitch the parts together.

Proof:

enter image description here

1
  • Thank you so much! I can't say I understood everything already but I'll sure try to understand this progressively. But I downloaded your model and will use it with my students in a practical exercise, if you don't mind, to show them the power of sharing tools on the internet with QGIS :-) – JBihin Feb 9 at 16:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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