2

I've created a layer style consisting of a rule-based renderer with multiple rules, each of them categorized into several categories. I load this style (qml) automatically to new layers that are added to my project.

However, not all layers contain data of all categories. My aim is now, to delete all categories within the rules, that don't contain any features.

But, how is it possible to manipulate the categories within rules in PyQGIS?

Here's my code so far:

source= os.path.join(path + "|layername=" + layer)
example= QgsVectorLayer(source, layer, "ogr")
QgsProject.instance().addMapLayer(example, True)
my_style = os.path.join(os.path.join(path, 'my_style.qml'))
example.loadNamedStyle(my_style)
renderer = example.renderer()
root_rule = renderer.rootRule()

I want to delete Category_2 in Rule_2

For example, I want to delete Category_2 in Rule_2 because there are no features within this category.

asked Jun 2 at 10:26
0

1 Answer 1

3

Something like this should do the trick- this will delete any unused rules taking into account parent rule and any sub-rule categories as a combined filter. Note that this code would need to be modified if there were more rule levels in the structure.

# Required imports if outside the Python console
from qgis.core import QgsProject, QgsFeatureRequest, QgsExpression
lyr = QgsProject.instance().mapLayersByName('layername')[0]
r_clone = lyr.renderer().clone()
rr = r_clone.rootRule()
for r in rr.descendants():
 filter_exp = r.filterExpression()
 ft_req = QgsFeatureRequest(QgsExpression(filter_exp))
 parent_rule_exp = r.parent().filterExpression()
 if parent_rule_exp:
 ft_req.combineFilterExpression(parent_rule_exp)
 filter_fts = lyr.getFeatures(ft_req)
 ft_count = len(list(filter_fts))
 if not ft_count:
 r.parent().removeChild(r)
lyr.setRenderer(r_clone)
iface.layerTreeView().refreshLayerSymbology(lyr.id())

This took just a couple of seconds on the test layer below with 39000 features.

Before:

enter image description here

After:

enter image description here

answered Jun 4 at 0:03
2
  • Thanks a lot for this great solution! The code works perfectly! Commented Jun 4 at 8:43
  • @Calidris, that's great. You're welcome :-) Commented Jun 4 at 8:54

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.