Using a QGIS Expression in the Layout Editor, how can one return the count of features matching a particular attribute value for an atlas feature, for example, "AREAS_Area".

In this particular example, the valid range of values for "Areas_Area" is 1-25. I would like to return the count of features matching the "Areas_Area" attributes for 1, 2, 3, etc.

Here is what I have currently, which provides me with an index (current Area number out of total Area numbers), as well as the page count (current feature number out of total number of features).

concat('Area: ',"Areas_AREA",' / ',maximum("Areas_AREA"),' | ','Segment: ',@atlas_featurenumber,' / ',@atlas_totalfeatures)

Image preview:
Image showing rendered expression. Reads "Area: 1 / 25 | Segment: 1 / 777"

So given the above information and the result I have in the preview, my expectation would be that it would instead read something more like:
Area: 1 / 25 | Segment: 1 / 13

1 Answer 1


You want to get two information dynamically in your atlas.

Get the index of the current segment within the group of segment with the same Areas_AREA

You have to use an id that is unique for this operation. I would use RIN for this but you can replace it with any id you have for your segment as long as it is in the same order that your atlas is ordered. You can use the formula array_agg() to get an array (kind of list) of all the RIN of segment that have Areas_AREA equal to Areas_AREA of your current segment. Then you can use array_find() to get the index of your current segment inside this array. You have to add +1 because the first element of an array have index 0.

array_find(array_agg("RIN", filter:="Areas_AREA"=attribute (@atlas_feature,'Areas_AREA'),"RIN") +1

OR a calculation with more explicit values :

array_find ( aggregate( @atlas_layername, aggregate:='array_agg', expression:="RIN", filter:="Areas_AREA" =attribute (@atlas_feature ,'Areas_AREA')), "RIN" )+1

The result should be 1 for the first segment then 2 then 3, then when your segment is in another area it should start from 1 again.

The number of segment that have the same Areas_AREA

To get the number of segment that have the same area id you can use the formula count() number of feature with Areas_AREA equal with the attribute Areas_AREA of your current atlas feature :

count(1, filter:="Areas_AREA" =attribute (@atlas_feature ,'Areas_AREA'))

The result should be a number equal to the number of feature for each area

Or you can also use array like before and use formula

array_length(array_agg("RIN", filter:="Areas_AREA"=attribute (@atlas_feature,'Areas_AREA')) 

The final formula would be something like :

concat('Area: ',"Areas_AREA",' / ',maximum("Areas_AREA"),' | ','Segment: ', 
array_find (aggregate( @atlas_layername, aggregate:='array_agg', expression:="RIN", filter:="Areas_AREA" =attribute (@atlas_feature ,'Areas_AREA')), "RIN" )+1, 
count(1, filter:="Areas_AREA" =attribute (@atlas_feature ,'Areas_AREA')))

Note : To make atlas of atlas the report function could be useful and could add title page for each group of segment with specific maps.

  • 1
    Wich version of qgis have you ? Have you tried the first and the second formula and what are the result ? Have you tried to delete the line jump in the last formula (sometimes the copy paste of line jump could be seen as character) ? Commented May 18, 2021 at 18:29
  • 1
    Thanks for the version I use 3.18.1 so it is not so far... If the first formula with array work well for you I have added a formula with array to get the count. Can you share the ordering formula you use for your atlas ? Have you tried to add your formula without verification from the expression editor ? Commented May 19, 2021 at 6:53
  • 1
    What is the result of this formula for atlas page : array_to_string (array_agg("RID", filter:="Areas_AREA"=attribute (@atlas_feature,'Areas_AREA')) is your RID of current feature present in the list ? Does this array change when your segment is in another Areas_AREA ? Commented May 21, 2021 at 12:27
  • 1
    And if you try array_to_string (array_agg("RID")) is the result the same that array_to_string ( aggregate( @atlas_layername, aggregate:='array_agg', expression:="RID")) ? If it work can you add after "RID" , filter:="Areas_AREA" =attribute (@atlas_feature ,'Areas_AREA') Commented May 25, 2021 at 9:54
  • 1
    Ok, so may be it work better with aggregate. Try array_find ( aggregate( @atlas_layername, aggregate:='array_agg', expression:="RIN", filter:="Areas_AREA" =attribute (@atlas_feature ,'Areas_AREA')), "RIN" )+1 it should give you the current RIN index among the RIN in the areas area. Commented May 25, 2021 at 19:58

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.