I have a point layer with two fields named "id" and "price", and a polygon layer with a field named "code_zone".

I need to get, for each polygon, the "id" of the point that has the highest value of "price", and this maximum value of the "price".

This is the beginning of my code:

for feature in layer_point.getFeatures():

   point_price = feature.attribute('price')
   point_geom = feature.geometry()

   for feat in layer_polygon.getFeatures():

      polygon_codeZone = feat.attribute('code_zone')
      polygon_maxValue = feat.attribute('max_value')
      polygon_geom = feat.geometry()

      if polygon_geom.contains(point_geom):

I tried with maximumValue(), but I get only the maximum value of the whole point layer and not the maximum value per polygon. What I am doing wrong?

As soon as I get these maximum values, I could fill them in my polygon layer with polygon_layer.changeAttributeValue() in the "max_value" field.

dpr = layer_polygon.dataProvider()
max_value_index = layer_polygon.fields().indexFromName('max_value')

for pol in layer_polygon.getFeatures():
    g = pol.geometry()
    req = QgsFeatureRequest(g.boundingBox()) # for performance
    prices = [p["price"] for p in layer_point.getFeatures(req) if g.contains(p.geometry())]
    dpr.changeAttributeValues({pol.id(): {max_value_index: max(prices)}})

enter image description here

| improve this answer | |
  • A big thank you, it looks perfect. I will test that tomorrow. – Ismail Dec 12 '19 at 13:24

The user of a SQL query is appropriate for your problem.

I created 2 tables: one with 2 polygons and another with 5 points.

enter image description here

Then I go to the database manager > Virtual layers > and open a SQL query window

I execute the following request :

--First part : For each polygon, the prices of all the points that are contained.
-- An identifier (fid) is generated for each polygon in descending order of price.

WITH all_price AS
 (SELECT row_number() over(partition by poly.id_poly  ORDER BY point.price DESC) as fid, 
 poly.id_poly, point.id, point.price
 FROM poly, point
 WHERE St_contains(poly.geometry,point.geometry)
 ORDER BY poly.id_poly, point.price)

 --When fid is equal to 1, it means that it is the highest price.
 SELECT all_price.id_poly, all_price.id, all_price.price
 FROM all_price 
 WHERE fid = 1

Result of the temporary table all_price on the left and the final result on the right. If you don't understand the request, I can give you more explanations.

enter image description here

| improve this answer | |
  • Thank you man, I didn't try to use SQL to solve my problem. Kadir's solution looks quicker to set up and run, but I'll still do some tests with SQL tomorrow to see what happens – Ismail Dec 12 '19 at 13:31

The function "join attributes by location (summary)" in QGIS will be a solution.

The polygon will be your "Input Layer", the point will be the "join layer". The predicate "intersect" may work well but you can try other if not.

You select "price" as the "field to summarize" and "max" as summary to calculate.

I hope it will solve your problem, if I haven't miss some part of your problem.

| improve this answer | |
  • The goal of the script is to find the maximum price value per polygon, and write in a second time those maximum values ​​to another field in the polygon layer. So i need to do all of that with a script – Ismail Dec 12 '19 at 10:50
  • This process create a new polygon layer with a new field with the maximum value as you expect (the two stpes). If the problem is that the information is in a new layer, then you can make an attribute join between your new polygon layer and your input layer to store it in one layer. – Corentin Lemaitre Dec 12 '19 at 11:07
  • I think it's possible to do that with a script, without creating new layers. Create a new polygon layer with "join by location", make an attribute join and delete the new polygon layer would be too long. I need something fast and automatic, because I will probably have to do this several times, with many layers of points and polygons – Ismail Dec 12 '19 at 11:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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