8

In the print composer when generating an atlas, does anyone know how to show he feature count per each atlas coverage feature?

For example, I have generated an atlas where each map is a different province (in Cambodia) containing a village point layer. When I click the sigma sign at the bottom of the legend for villages, the feature count will calculate the entire country's number of villages, not for the individual province's number of villages.

Does anyone know how to get a feature count in for the province showing in the atlas?

2
  • Do you mean 2.18 or 2.8? Typo or not?
    – jlSta
    Jan 17, 2018 at 15:49
  • @jlSta The original question was for 2.8 (I posted it in 2015). But glad to know it works for 2.18
    – Weevils
    Jan 18, 2018 at 17:46

2 Answers 2

7

This works for me: use the aggregate() expression in a text label, with within($geometry,@atlas_geometry) as a filter for points within your atlas feature.

The full syntax in your text label would be

[% aggregate('LAYER_NAME','count',"UNIQUE_NON_NULL_ATTRIBUTE_FOR_COUNTING",within($geometry,@atlas_geometry)) %]

That will count all the points in your specified layer - by an unique non-null attribute, so each point is distinct - but only if the point geometry is within the atlas geometry.

The [% %] is required to make the expression work. And note the quotation marks - you must use double quotes for the attribute name.

As a bonus you can add further filters, so to address one of the comments above, you can modify the filter to say within($geometry,@atlas_geometry) AND "village" = 'A', or whatever combination.

I haven't extensively tested this out, especially on large/complex datasets, but it seems to do the job.

2
  • 1
    This answer is for 2.18 but it works!
    – jlSta
    Jan 17, 2018 at 15:49
  • Yes, I should have mentioned that :-) Now with the impending release of 3.0 you could do even more cool things right in the expression builder, with the new collect aggregate function, which groups geometries together. For example, you can test whether a point geometry is within the atlas geometry, AND another collective geometry - say, all development areas, without having to specify by attribute value as you had to before with geometry(get_feature('layer',"attribute",'value'))!
    – she_weeds
    Jan 18, 2018 at 5:04
5

You need to create a script counting point within the current atlas geometry.

In the expression function editor add this code:

from qgis.core import *
from qgis.gui import *
from qgis.utils import iface

@qgsfunction(args="auto", group='Custom')
def countPointsInCurrentAltlasFeature(pointLayerName, geomAtlas, feature, parent):
    # If point geom is empty, return 0
    if (geomAtlas is None):
        return 0

    # Get point layer reference from layername
    pointLayer = QgsMapLayerRegistry.instance().mapLayersByName(pointLayerName)[0]

    # Raise if layer not found
    if pointLayer is None:
        raise Exception("Layer not found: " + pointLayerName)

    # Count point within current Atlas feature
    countPoint = 0
    for pointFeature in pointLayer.getFeatures():
        pointGeom = pointFeature.geometry()
        if (pointGeom is None):
            continue
        if pointGeom.within(geomAtlas):
            countPoint += 1

    return countPoint

Use the new function as an expression for a Print Composer label like:

Villages in province: [% countPointsInCurrentAltlasFeature( 'Villages', $atlasgeometry)%]

enter image description here

enter image description here

4
  • This is great. Many thanks. Just to clarify, when using the above expression in the print composer, I need to add it as a title/text, not directly into the legend. Is this correct?
    – Weevils
    Jun 29, 2015 at 12:27
  • Yes, it is a text label. Currently there are no databinding to legend items.
    – Jakob
    Jun 30, 2015 at 6:00
  • Is there anything new on the latest release of QGis regarding this topic, cause i want same thing but is there anything more simple? Jul 14, 2017 at 9:40
  • Additional question: This is exactly what I want to do, except I have different kinds of "villages" named A, B, C, etc. So I need to filter by that. Does anyone have a clue on how to achieve that? Thanks.
    – johlund
    Sep 19, 2017 at 8:43

Your Answer

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

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