2

I'd like to write an expression function in QGIS 2.18 to select features based on the value of their attributes. How can I access attribute values within my function?

I have noticed that in QGIS 2.18.x, the selection does not seem to work when accessing feature attributes as feature['attribute'].

For example, I tried the following functions to select features from Natural Earth's Populated Places Simple dataset. The three functions below select all the capital cities in QGIS 2.14.12, but no features are selected in QGIS 2.18.7.

@qgsfunction(args=0, group='Custom')
def select_country_capitals_1(value1, feature, parent):
    """ Select all the capital cities """
    return feature['featurecla'] == 'Admin-0 capital'

@qgsfunction(args=0, group='Custom')
def select_country_capitals_2(value1, feature, parent):
    return feature[3] == 'Admin-0 capital'

@qgsfunction(args=0, group='Custom')
def select_country_capitals_3(value1, feature, parent):
    return feature.attributes()[3] == 'Admin-0 capital'

Agreed that the above is possible with a simple query "featurecla" = 'Admin-0 capital' from the expression engine, but I would like to access attribute values within the function and perform some further computation.

2 Answers 2

3

Another way to access feature attributes within expression functions in QGIS 2.18 would be to specify them in referenced_columns within the @qgsfunction decorator.

For example, the function should be modified as below, and can be called as select_country_capitals()

@qgsfunction(args='auto', group='Custom', referenced_columns=['featurecla'])
def select_country_capitals(feature, parent):
    """ Select all the capital cities """
    if feature['featurecla'] == 'Admin-0 capital':
        return value
2

I guess some things have changed since QGIS 2.14 but the following should work for QGIS 2.18:

@qgsfunction(args='auto', group='Custom')
def select_country_capitals_1(value, feature, parent):
    """ Select all the capital cities """
    if feature.attributes()[3] == 'Admin-0 capital':
        return value

Then use the following expression to call the function:

select_country_capitals_1("featurecla")

Where "featurecla" is your field name.


Edit:

If you want to include multiple fields in your expression, you could add another parameter in your function and use the logical operator and in your if statement to add another condition. For example, if we want to select all attributes which has the value Admin-0 capital in the "featurecla" field AND has a _"pop_max_" greater than 10000 then we could use:

@qgsfunction(args='auto', group='Custom')
def select_country_capitals_1(field1, field2, feature, parent):
    """ Select all the capital cities """
    if feature.attributes()[0] == 'Admin-0 capital' and feature.attributes()[1] > 10000:
        return field1

And call this using:

select_country_capitals("featurecla", "pop_max")

Note: the code assumes the fields "featurecla" and "pop_max" have a field index of 0 and 1 respectively.

2
  • Hi Joseph, thanks a lot for your answer. It works. Could you also help me with the case when I want to use multiple feature attributes within my function? For example if I need the fields "featurecla" and "pop_max", will the function then be called as select_country_capitals("featurecla", "pop_max")? I tried that but am getting a Parser error, select_country_capitals() is called with the wrong number of arguments. I should probably also let you know that following your code, I set args='auto' in the qgsfunction decorator, but I still get the error.
    – Simran
    Commented Apr 26, 2017 at 18:51
  • @Simran - Most welcome, glad it worked! Edited my post to include a possible method to use two fields :)
    – Joseph
    Commented Apr 27, 2017 at 11:41

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.