11

The question: How is it possible to get the value of an attribute in another layer?

What is clear: When using QGIS expressions on a layer, it is possible to relate to features of another layer with get_feature(layer,attribute,value) (enter the value and get the first feature with this value) or get_feature_by_id(layer,feature_id) (you enter th id of the feature you want to get). Adding geometry(feature) gets the geometry.

The problem: I found no expression that allows to get the values of a certain field - like: enter the id of a feature and get the content of the field "value" - something like (pseudo-expression): attribute_value(feature). The idea is, by way of example, to have access to a point layer and get all the points where field "value" > 500.

This screenshot shows a successful connection (black line) from the start point of the red line to the point with the value = 1486. However, I want to get a connecting line from the start point of the line to all blue points with value > 500:

enter image description here

What I tried: I tested different combinations with aggregate(layer,aggregate,expression[,filter][,concatenator=''][,order_by]), however I was not able to get an aggregate of "value" in a numerical form, I always had to convert them to stings:

  1. aggregate( 'points', aggregate:='concatenate', expression:="value", filter:= ("value" > 500), concatenator:=',') produces an error: Could not calculat aggregate for: value
  2. The shorter version aggregate( 'points', 'concatenate', "value") produces an output of NULL
  3. aggregate( 'points', 'concatenate', to_string ("value")) works, but produces a long string without delimeters, output looks like: 129594124217708841125620148663516710931369194910474691822123…' Adding concatenator:=',' does not help. But the main problem is that the values are converted to strings, so no way to use mathematical operators.
  4. Update: the solution by MrXsquared helped me to create almost what I want, but if the values are not unique, it selects just the first feature. See this screenshot, I created the points with value > 500 as an additonal red points layer with geometry generator. There are two points with the value 513, but only one is created with the geometry generator , the other one not - in fact, the first one is rendered twice, as a duplicate. This is because get_feature () only gets the first feature that matches the input value.

enter image description here

This is the expression used:

collect_geometries (
    array_foreach (
        aggregate (
            'points',
            'array_agg',
            "value",
            "value">500 
        ) ,
    geometry (
        get_feature (
            'points', 
            'value', 
            @element
        )
    )
    )
)

I'm quite stuck here, what do I miss?

I want to get the feature id of all features with "value">500:

enter image description here

0

2 Answers 2

9

To get an array of all your values of a different layer with condition you can use

 aggregate('layer','array_agg',"fieldname","fieldname">50)

or

 aggregate('layer','array_agg',$id,"fieldname">50)

to get the feature IDs. You could also apply $currentfeature to get the features or $geometry for their geometries instead of $id.

So to reproduce your result at 3 with delimiters you could use array_to_string(aggregate('layer','array_agg',$id,"fieldname">50),',') for example, but this is of course a string again.

Also you can access the attributes as stated in "The Problem" via attribute(get_feature_by_id('layer',feature_id),'field') or attributes(get_feature_by_id('layer',feature_id)).


So seeing your screenshot I get what you are trying to do. This reminds somehow on Displaying vertex coordinates of a polygon or line without creating a new layer. We have quite the same issue here. If you wish to draw several lines from one feature to several destinations, one somehow would need the ability to iterate. Not sure how this could be done. Yet...

3
  • Thank you @MrXsquared, that helped me a step further, see additon in the question (What I tried, no. 4)
    – Babel
    Dec 11, 2020 at 22:41
  • array_foreach is to my knowledge the only way to kind of iterate with QGIS expressions. That works, only problem left is just how to include multiple features with the same attribute value - get_feature() delivers only the first one...
    – Babel
    Dec 11, 2020 at 22:44
  • The issues are different, because in the linked post it was required to get individual features (each point) while here it is OK to have a single multi-line. We can iterate... and then collect (but "just" iterating looked like it was not possible)
    – JGH
    Dec 12, 2020 at 12:34
8

Instead of collecting the values and selecting back the geometry using this value, you can directly collect the geometries.

collect_geometries (
    array_foreach (
        aggregate (
            'points',
            'array_agg',
            $geometry,
            "value">500 
        ) ,
    make_line(start_point($geometry),@element)
    )
)

enter image description here

2
  • Solution works! So $geometry in this case refers to the geometries in the other layer, doesn't it? I thought $geometry cannot but refer to the current layer (the one working on). In your example, the first instance of $geometry refers to the point layer, the second $geometry refers to the line layer - correct?
    – Babel
    Dec 12, 2020 at 14:17
  • @babel Yes, within the aggregate function, the joined (point) layer becomes the "current" one, and we can access the source (line) using @parent See the filter portion of the doc
    – JGH
    Dec 12, 2020 at 19:20

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.