2

Context: the script selects features from a layer which overlaps another one above a certain percentage and creates a new layer with these selected features. I do not manage to copy the attributes from the attributes table, only the ID is reported.

What am i doing wrong?

Here is the code:

mapcanvas = iface.mapCanvas()

layers = mapcanvas.layers()

#for Severity
feats_lyr1 = [ feat for feat in layers[0].getFeatures() ]

#for Basins800
feats_lyr2 = [ feat for feat in layers[1].getFeatures() ]

selected_feats = []

print "processing..."

for i, feat1 in enumerate(feats_lyr1):
    for j, feat2 in enumerate(feats_lyr2):
        if feat1.geometry().intersects(feat2.geometry()):
            area1 = feat1.geometry().intersection(feat2.geometry()).area()
            area2 = feat2.geometry().area()
            crit =area1/area2
            if crit > 0.8:
                selected_feats.append(feat2)

epsg = layers[0].crs().postgisSrid()

uri = "Polygon?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           "mem_layer",
                           "memory")



lyr = mem_layer.dataProvider()

for i, feat in enumerate(selected_feats):
    feat.setAttributes(selected_feats[i].attributes())
    lyr.addFeatures([feat])

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)
print "done..."
  • Your issue is because you need to create one field, with QVariant, for each one you want to appear in attributes table of memory layer. Defined uri only allows id field. – xunilk Dec 21 '17 at 12:16
0

Your issue is because you need to create one field, with QVariant, for each one you want to appear in attributes table of memory layer. Defined uri only allows id field. For instance, at following image you can observe that attributes table of polygon8 (equivalent to your Basins800) has several fields.

enter image description here

Suppose that I want to copy 'values' field in attributes table of resulting memory layer (order must be considered), I need these additional lines in my code:

.
.
.
field = QgsField("values", QVariant.Int)
lyr.addAttributes([field])
mem_layer.updateFields()
.
.
.

Adding them to your code, it is as follow:

from qgis.PyQt.QtCore import QVariant

mapcanvas = iface.mapCanvas()

layers = mapcanvas.layers()

#for Severity
feats_lyr1 = [ feat for feat in layers[0].getFeatures() ]

#for Basins800
feats_lyr2 = [ feat for feat in layers[1].getFeatures() ]

selected_feats = []

print "processing..."

for i, feat1 in enumerate(feats_lyr1):
    for j, feat2 in enumerate(feats_lyr2):
        if feat1.geometry().intersects(feat2.geometry()):
            area1 = feat1.geometry().intersection(feat2.geometry()).area()
            area2 = feat2.geometry().area()
            crit =area1/area2
            if crit > 0.6:
                selected_feats.append(feat2)

epsg = layers[0].crs().postgisSrid()

uri = "Polygon?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           "mem_layer",
                           "memory")

lyr = mem_layer.dataProvider()

#added lines
field = QgsField("values", QVariant.Int)
lyr.addAttributes([field])
mem_layer.updateFields()
#######################

for i, feat in enumerate(selected_feats):
    feat.setAttributes(selected_feats[i].attributes())
    lyr.addFeatures([feat])

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)
print "done..."

After running the code at Python Console of QGIS (note that it was used crit > 0.6 with my shapefiles to get a result), it can be observed that attributes table of created memory layer has desired field.

enter image description here

If you want specific fields in your attributes table you need to extract them from selected_feats[i].attributes() matrix list. It is not too difficult. For instance, in Python Console I have:

>>>attributes = [ feat.attributes() for feat in selected_feats ]
>>>attributes
[[1.0, 43, 1351.0, 2330.0, 1, 280502186.97, 65657.871, 500, 27, u'my test', 3, 1], [6.0, 83, 1538.0, 1772.0, 6, 127035968.31, 46664.327, 20, 84, u'my test', 4, 1]]

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.