I have a shapefile and I need to update a field with calculation results. In the calculation I'm iterating through two list with equal items as features of the shapefile. The sum of the list items gets multiplied with an integer value (constant). The field name which needs to be updated is "SH"
.
Here is how I tried solving it with some example data:
a = [134.24, 134.24, 134.24, 134.99]
b = [58.848430067837946, 70.46615125391358, 63.02756211443306, 60.662300968221174]
c = 0.6673779977746334
newlayer = iface.addVectorLayer(outfile_rel_revised,"", "ogr")
newlayer.setCrs(crsSrc)
with edit(newlayer):
for rel_feature in newlayer.getFeatures():
for i in a:
for j in b:
rel_feature['SH'] = ((i + j)* c)
newlayer.updateFeature(rel_feature)
break
If I run this, I get no error but the field is not updated. For example the calculation for feature 1 should look like this: (134.24 + 58.848430067837946)*0.6673779977746334
The finished result should look like this:
1 Answer 1
Try this logic:
a = [134.24, 134.24, 134.24, 134.99]
b = [58.848430067837946, 70.46615125391358, 63.02756211443306, 60.662300968221174]
c = 0.6673779977746334
newlayer = iface.activeLayer()
with edit(newlayer):
for i,rel_feature in enumerate(newlayer.getFeatures()):
rel_feature['SH'] = round((a[i] + b[i])*c,2)
newlayer.updateFeature(rel_feature)
Make sure your file is not write protected and the field (SH
) is of type real
.
This should actually work. If for some reason it does not update the file, you can give changeAttributeValue()
method a try:
a = [134.24, 134.24, 134.24, 134.99]
b = [58.848430067837946, 70.46615125391358, 63.02756211443306, 60.662300968221174]
c = 0.6673779977746334
newlayer = iface.activeLayer()
with edit(newlayer):
for i,rel_feature in enumerate(newlayer.getFeatures()):
result = round((a[i] + b[i])*c,2)
newlayer.changeAttributeValue(rel_feature.id(), newlayer.fields().indexOf('SH'), result)
With this kind of logic an order by request might make sense:
a = [134.24, 134.24, 134.24, 134.99]
b = [58.848430067837946, 70.46615125391358, 63.02756211443306, 60.662300968221174]
c = 0.6673779977746334
newlayer = iface.activeLayer()
request = QgsFeatureRequest()
clause = QgsFeatureRequest.OrderByClause('id', ascending=True)
orderby = QgsFeatureRequest.OrderBy([clause])
request.setOrderBy(orderby)
with edit(newlayer):
for i,rel_feature in enumerate(newlayer.getFeatures(request)):
result = round((a[i] + b[i])*c,2)
newlayer.changeAttributeValue(rel_feature.id(), newlayer.fields().indexOf('SH'), result)
-
Thank you!! The first code worked fine on the first try, but then I tried to extent your code to get another two fields updated. Like this:
with edit(newlayer): for i,rel_feature in enumerate(newlayer.getFeatures()): rel_feature['SH'] = round((a[i] + b[i])*c,2) rel_feature['SH30'] = round((a[i] + b[i] + (wind1 * 100))*c,2) rel_feature['SH50'] = round((a[i] + b[i] + (wind2 * 100))*c,2) newlayer.updateFeature(rel_feature)
now I get this error TypeError: unsupported operand type(s) for *: 'float' and 'QgsColorRampShader'. Any ideas?Simon– Simon2022年05月02日 16:19:45 +00:00Commented May 2, 2022 at 16:19 -
@Simon I guess either variable
wind1
orwind2
contains aQgsColorRampShader
object. Make sure it contains a numerical value. The error just says that you cannot multiply aQgsColorRampShader
object.MrXsquared– MrXsquared2022年05月02日 18:55:37 +00:00Commented May 2, 2022 at 18:55 -
I solved the error, but the fields won't update anymore. If I print the result it's correct but it doesn't update. I also tried to write the result into a list and update this way [gis.stackexchange.com/a/286780/204059] but also no update. I updated another field of this layer with this logic [gis.stackexchange.com/a/429009/204059] and had no problems. I don't unterstand why it doesn't update the fields!!Simon– Simon2022年05月02日 20:23:09 +00:00Commented May 2, 2022 at 20:23
Explore related questions
See similar questions with these tags.
newlayer
(e.g.newlayer = iface.activeLayer()
)? Apart from that you could also assign a5
to every feature directly without calculating ;)5
to all rows once (due to thebreak
, thej
loop only fires once)