Iterate through list of field names and calculate fields with PyQGIS?

The name of the pictureThe name of the pictureThe name of the pictureClash 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.










share|improve this question









New contributor




Matt Needle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

























    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.










    share|improve this question









    New contributor




    Matt Needle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.





















      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.










      share|improve this question









      New contributor




      Matt Needle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      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






      share|improve this question









      New contributor




      Matt Needle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      Matt Needle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 9 mins ago









      Andre Silva

      6,593113475




      6,593113475






      New contributor




      Matt Needle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 2 hours ago









      Matt Needle

      183




      183




      New contributor




      Matt Needle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Matt Needle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Matt Needle is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.




















          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()





          share|improve this answer


















          • 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










          Your Answer







          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "79"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );






          Matt Needle is a new contributor. Be nice, and check out our Code of Conduct.









           

          draft saved


          draft discarded


















          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






























          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()





          share|improve this answer


















          • 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














          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()





          share|improve this answer


















          • 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












          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()





          share|improve this answer














          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()






          share|improve this answer














          share|improve this answer



          share|improve this answer








          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












          • 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










          Matt Needle is a new contributor. Be nice, and check out our Code of Conduct.









           

          draft saved


          draft discarded


















          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.













           


          draft saved


          draft discarded














          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













































































          Comments

          Popular posts from this blog

          Long meetings (6-7 hours a day): Being “babysat” by supervisor

          Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

          Confectionery