Iterate through list of field names and calculate fields with PyQGIS?
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
3
down vote
favorite
I am using QGIS 3.2.1 Bonn 64 bit on Windows 10. I would like to loop through a list of field names and perform calculations on each field. Only the first loop in the iteration performs any calculations. The rest are skipped.
result_path = r"D:QGIShex_results.geojson"
tracks = QgsProject.instance().mapLayersByName("patrol_tracks")[0]
result = QgsProject.instance().mapLayersByName("hex_results")[0]
t = tracks.getFeatures()
r = result.getFeatures()
r_prov = result.dataProvider()
r_fields = r_prov.fieldNameMap()
months = [x for x in processing.run("qgis:listuniquevalues", 'INPUT':tracks,'FIELDS':"Month_Year",'OUTPUT':'u')['UNIQUE_VALUES'].split(";")]
for m in months:
result.startEditing()
field_index = result.fields().lookupField(m)
print (m)
print (field_index)
a = field_index : 0
for feat in r:
fid = feat.id()
r_prov.changeAttributeValues(fid : a)
result.commitChanges()
The print calls work for every list item but the field attributes are only altered for the first iteration.
Another method I have tried (using the same variable names as above) is:
for m in months:
processing.run('qgis:fieldcalculator', 'INPUT':result, 'FIELD_NAME':m, 'FIELD_TYPE':1, 'FIELD_LENGTH':10, 'FIELD_PRECISION':0, 'NEW_FIELD': False, 'FORMULA':'0', 'OUTPUT':result_path)
But with the same result - only the first field in the list is calculated. This code will be part of a more complex script that calculates field values based on the intersection of selected features - which is more or less working up until this point.
Any suggestions? I wondered if the dataProvider needs to be refreshed or updated after each iteration but commitChanges(), added later, doesn't seem to have any effect.
python pyqgis field-calculator qgis-3.0 loop
New contributor
add a comment |Â
up vote
3
down vote
favorite
I am using QGIS 3.2.1 Bonn 64 bit on Windows 10. I would like to loop through a list of field names and perform calculations on each field. Only the first loop in the iteration performs any calculations. The rest are skipped.
result_path = r"D:QGIShex_results.geojson"
tracks = QgsProject.instance().mapLayersByName("patrol_tracks")[0]
result = QgsProject.instance().mapLayersByName("hex_results")[0]
t = tracks.getFeatures()
r = result.getFeatures()
r_prov = result.dataProvider()
r_fields = r_prov.fieldNameMap()
months = [x for x in processing.run("qgis:listuniquevalues", 'INPUT':tracks,'FIELDS':"Month_Year",'OUTPUT':'u')['UNIQUE_VALUES'].split(";")]
for m in months:
result.startEditing()
field_index = result.fields().lookupField(m)
print (m)
print (field_index)
a = field_index : 0
for feat in r:
fid = feat.id()
r_prov.changeAttributeValues(fid : a)
result.commitChanges()
The print calls work for every list item but the field attributes are only altered for the first iteration.
Another method I have tried (using the same variable names as above) is:
for m in months:
processing.run('qgis:fieldcalculator', 'INPUT':result, 'FIELD_NAME':m, 'FIELD_TYPE':1, 'FIELD_LENGTH':10, 'FIELD_PRECISION':0, 'NEW_FIELD': False, 'FORMULA':'0', 'OUTPUT':result_path)
But with the same result - only the first field in the list is calculated. This code will be part of a more complex script that calculates field values based on the intersection of selected features - which is more or less working up until this point.
Any suggestions? I wondered if the dataProvider needs to be refreshed or updated after each iteration but commitChanges(), added later, doesn't seem to have any effect.
python pyqgis field-calculator qgis-3.0 loop
New contributor
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I am using QGIS 3.2.1 Bonn 64 bit on Windows 10. I would like to loop through a list of field names and perform calculations on each field. Only the first loop in the iteration performs any calculations. The rest are skipped.
result_path = r"D:QGIShex_results.geojson"
tracks = QgsProject.instance().mapLayersByName("patrol_tracks")[0]
result = QgsProject.instance().mapLayersByName("hex_results")[0]
t = tracks.getFeatures()
r = result.getFeatures()
r_prov = result.dataProvider()
r_fields = r_prov.fieldNameMap()
months = [x for x in processing.run("qgis:listuniquevalues", 'INPUT':tracks,'FIELDS':"Month_Year",'OUTPUT':'u')['UNIQUE_VALUES'].split(";")]
for m in months:
result.startEditing()
field_index = result.fields().lookupField(m)
print (m)
print (field_index)
a = field_index : 0
for feat in r:
fid = feat.id()
r_prov.changeAttributeValues(fid : a)
result.commitChanges()
The print calls work for every list item but the field attributes are only altered for the first iteration.
Another method I have tried (using the same variable names as above) is:
for m in months:
processing.run('qgis:fieldcalculator', 'INPUT':result, 'FIELD_NAME':m, 'FIELD_TYPE':1, 'FIELD_LENGTH':10, 'FIELD_PRECISION':0, 'NEW_FIELD': False, 'FORMULA':'0', 'OUTPUT':result_path)
But with the same result - only the first field in the list is calculated. This code will be part of a more complex script that calculates field values based on the intersection of selected features - which is more or less working up until this point.
Any suggestions? I wondered if the dataProvider needs to be refreshed or updated after each iteration but commitChanges(), added later, doesn't seem to have any effect.
python pyqgis field-calculator qgis-3.0 loop
New contributor
I am using QGIS 3.2.1 Bonn 64 bit on Windows 10. I would like to loop through a list of field names and perform calculations on each field. Only the first loop in the iteration performs any calculations. The rest are skipped.
result_path = r"D:QGIShex_results.geojson"
tracks = QgsProject.instance().mapLayersByName("patrol_tracks")[0]
result = QgsProject.instance().mapLayersByName("hex_results")[0]
t = tracks.getFeatures()
r = result.getFeatures()
r_prov = result.dataProvider()
r_fields = r_prov.fieldNameMap()
months = [x for x in processing.run("qgis:listuniquevalues", 'INPUT':tracks,'FIELDS':"Month_Year",'OUTPUT':'u')['UNIQUE_VALUES'].split(";")]
for m in months:
result.startEditing()
field_index = result.fields().lookupField(m)
print (m)
print (field_index)
a = field_index : 0
for feat in r:
fid = feat.id()
r_prov.changeAttributeValues(fid : a)
result.commitChanges()
The print calls work for every list item but the field attributes are only altered for the first iteration.
Another method I have tried (using the same variable names as above) is:
for m in months:
processing.run('qgis:fieldcalculator', 'INPUT':result, 'FIELD_NAME':m, 'FIELD_TYPE':1, 'FIELD_LENGTH':10, 'FIELD_PRECISION':0, 'NEW_FIELD': False, 'FORMULA':'0', 'OUTPUT':result_path)
But with the same result - only the first field in the list is calculated. This code will be part of a more complex script that calculates field values based on the intersection of selected features - which is more or less working up until this point.
Any suggestions? I wondered if the dataProvider needs to be refreshed or updated after each iteration but commitChanges(), added later, doesn't seem to have any effect.
python pyqgis field-calculator qgis-3.0 loop
python pyqgis field-calculator qgis-3.0 loop
New contributor
New contributor
edited 9 mins ago
Andre Silva
6,593113475
6,593113475
New contributor
asked 2 hours ago
Matt Needle
183
183
New contributor
New contributor
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
4
down vote
accepted
I belive the QgsFeatureIterator is closed after returning all features.
Example:
>>layer = iface.activeLayer()
>>feats = layer.getFeatures()
>>[f['GRID_ID'] for f in feats]
['AP7', 'AP8', 'AP9', 'AP3', 'AP4', 'AP5', 'AP6', 'AP1', 'AP2']
>>[f['GRID_ID'] for f in feats]
#No more features are return after used once
>>feats = layer.getFeatures() #Recreate it
>>[f['GRID_ID'] for f in feats]
['AP7', 'AP8', 'AP9', 'AP3', 'AP4', 'AP5', 'AP6', 'AP1', 'AP2']
So in your case recreate it for each iteration:
...
for m in months:
result.startEditing()
field_index = result.fields().lookupField(m)
print (m)
print (field_index)
a = field_index : 0
for feat in r:
fid = feat.id()
r_prov.changeAttributeValues(fid : a)
result.commitChanges()
r = result.getFeatures()
2
You are absolutely right. The QgsFeatureIterator was empty after the first iteration. It was as simple as adding the last line: r = result.getFeatures() and just for the record it works even after removing the startEditing() and commitChanges() methods. Many thanks.
â Matt Needle
47 mins ago
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
accepted
I belive the QgsFeatureIterator is closed after returning all features.
Example:
>>layer = iface.activeLayer()
>>feats = layer.getFeatures()
>>[f['GRID_ID'] for f in feats]
['AP7', 'AP8', 'AP9', 'AP3', 'AP4', 'AP5', 'AP6', 'AP1', 'AP2']
>>[f['GRID_ID'] for f in feats]
#No more features are return after used once
>>feats = layer.getFeatures() #Recreate it
>>[f['GRID_ID'] for f in feats]
['AP7', 'AP8', 'AP9', 'AP3', 'AP4', 'AP5', 'AP6', 'AP1', 'AP2']
So in your case recreate it for each iteration:
...
for m in months:
result.startEditing()
field_index = result.fields().lookupField(m)
print (m)
print (field_index)
a = field_index : 0
for feat in r:
fid = feat.id()
r_prov.changeAttributeValues(fid : a)
result.commitChanges()
r = result.getFeatures()
2
You are absolutely right. The QgsFeatureIterator was empty after the first iteration. It was as simple as adding the last line: r = result.getFeatures() and just for the record it works even after removing the startEditing() and commitChanges() methods. Many thanks.
â Matt Needle
47 mins ago
add a comment |Â
up vote
4
down vote
accepted
I belive the QgsFeatureIterator is closed after returning all features.
Example:
>>layer = iface.activeLayer()
>>feats = layer.getFeatures()
>>[f['GRID_ID'] for f in feats]
['AP7', 'AP8', 'AP9', 'AP3', 'AP4', 'AP5', 'AP6', 'AP1', 'AP2']
>>[f['GRID_ID'] for f in feats]
#No more features are return after used once
>>feats = layer.getFeatures() #Recreate it
>>[f['GRID_ID'] for f in feats]
['AP7', 'AP8', 'AP9', 'AP3', 'AP4', 'AP5', 'AP6', 'AP1', 'AP2']
So in your case recreate it for each iteration:
...
for m in months:
result.startEditing()
field_index = result.fields().lookupField(m)
print (m)
print (field_index)
a = field_index : 0
for feat in r:
fid = feat.id()
r_prov.changeAttributeValues(fid : a)
result.commitChanges()
r = result.getFeatures()
2
You are absolutely right. The QgsFeatureIterator was empty after the first iteration. It was as simple as adding the last line: r = result.getFeatures() and just for the record it works even after removing the startEditing() and commitChanges() methods. Many thanks.
â Matt Needle
47 mins ago
add a comment |Â
up vote
4
down vote
accepted
up vote
4
down vote
accepted
I belive the QgsFeatureIterator is closed after returning all features.
Example:
>>layer = iface.activeLayer()
>>feats = layer.getFeatures()
>>[f['GRID_ID'] for f in feats]
['AP7', 'AP8', 'AP9', 'AP3', 'AP4', 'AP5', 'AP6', 'AP1', 'AP2']
>>[f['GRID_ID'] for f in feats]
#No more features are return after used once
>>feats = layer.getFeatures() #Recreate it
>>[f['GRID_ID'] for f in feats]
['AP7', 'AP8', 'AP9', 'AP3', 'AP4', 'AP5', 'AP6', 'AP1', 'AP2']
So in your case recreate it for each iteration:
...
for m in months:
result.startEditing()
field_index = result.fields().lookupField(m)
print (m)
print (field_index)
a = field_index : 0
for feat in r:
fid = feat.id()
r_prov.changeAttributeValues(fid : a)
result.commitChanges()
r = result.getFeatures()
I belive the QgsFeatureIterator is closed after returning all features.
Example:
>>layer = iface.activeLayer()
>>feats = layer.getFeatures()
>>[f['GRID_ID'] for f in feats]
['AP7', 'AP8', 'AP9', 'AP3', 'AP4', 'AP5', 'AP6', 'AP1', 'AP2']
>>[f['GRID_ID'] for f in feats]
#No more features are return after used once
>>feats = layer.getFeatures() #Recreate it
>>[f['GRID_ID'] for f in feats]
['AP7', 'AP8', 'AP9', 'AP3', 'AP4', 'AP5', 'AP6', 'AP1', 'AP2']
So in your case recreate it for each iteration:
...
for m in months:
result.startEditing()
field_index = result.fields().lookupField(m)
print (m)
print (field_index)
a = field_index : 0
for feat in r:
fid = feat.id()
r_prov.changeAttributeValues(fid : a)
result.commitChanges()
r = result.getFeatures()
edited 33 mins ago
answered 1 hour ago
BERA
11.6k41537
11.6k41537
2
You are absolutely right. The QgsFeatureIterator was empty after the first iteration. It was as simple as adding the last line: r = result.getFeatures() and just for the record it works even after removing the startEditing() and commitChanges() methods. Many thanks.
â Matt Needle
47 mins ago
add a comment |Â
2
You are absolutely right. The QgsFeatureIterator was empty after the first iteration. It was as simple as adding the last line: r = result.getFeatures() and just for the record it works even after removing the startEditing() and commitChanges() methods. Many thanks.
â Matt Needle
47 mins ago
2
2
You are absolutely right. The QgsFeatureIterator was empty after the first iteration. It was as simple as adding the last line: r = result.getFeatures() and just for the record it works even after removing the startEditing() and commitChanges() methods. Many thanks.
â Matt Needle
47 mins ago
You are absolutely right. The QgsFeatureIterator was empty after the first iteration. It was as simple as adding the last line: r = result.getFeatures() and just for the record it works even after removing the startEditing() and commitChanges() methods. Many thanks.
â Matt Needle
47 mins ago
add a comment |Â
Matt Needle is a new contributor. Be nice, and check out our Code of Conduct.
Matt Needle is a new contributor. Be nice, and check out our Code of Conduct.
Matt Needle is a new contributor. Be nice, and check out our Code of Conduct.
Matt Needle is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fgis.stackexchange.com%2fquestions%2f296547%2fiterate-through-list-of-field-names-and-calculate-fields-with-pyqgis%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password