4

I just want to count the values in a list (NEIGHBORS) for each object in my layer and put the result in a column (NUMBER).

enter image description here

My code is not working

from qgis.PyQt.QtCore import QVariant
test = iface.activeLayer()
v1 =  QgsVectorLayer("NUMBER")
with edit (v1):
    for f in v1.getFeatures():
        f ["NUMBER"] = f[len('NEIGHBORS')]
        v1.updateFeature(f)

and has the following error.

Traceback (most recent call last):
  File "C:\PROGRA~1\QGIS31~1.15\apps\Python39\lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
  File "<string>", line 36, in <module>
  File "C:\PROGRA~1/QGIS31~1.15/apps/qgis-ltr/./python\qgis\core\additions\edit.py", line 38, in __enter__
    assert self.layer.startEditing()
AssertionError

Do you have an idea?

2
  • 1
    Furthermore, probably len(f['NEIGHBORS'].split(',')), otherwise it will just return the length of the string
    – Matt
    Feb 1, 2022 at 22:57
  • As per the help center please do not include chit chat like thanks within your posts.
    – PolyGeo
    Feb 2, 2022 at 7:27

1 Answer 1

8

The error is because you are creating and trying to edit an invalid layer. You do not need to create a new layer object at all. All you need is this:

lyr = iface.activeLayer()
fld_ix = lyr.fields().lookupField('NUMBER')
atts_map = {f.id(): {fld_ix: len(f['NEIGHBORS'].split(','))} for f in lyr.getFeatures() if f['NEIGHBORS'] != NULL}
#print(atts_map)
lyr.dataProvider().changeAttributeValues(atts_map)

Select your layer in the TOC and Run.

Test result:

enter image description here

You can find more information in the Pyqgis Developer Cookbook.

9
  • @fcka, if your field value is really a list then len(f['NEIGHBORS']) is what you want. I have edited my answer. Please try it again.
    – Ben W
    Feb 2, 2022 at 9:49
  • @ Ben W , as much for me, it's not a list, I think it's a dictionary with keys corresponding to the id of the objects and with values corresponding to the number of the objects. so how can we retrieve in a new attribute only the list of dict.values()?
    – fcka
    Feb 2, 2022 at 14:30
  • @fcka You must do some debugging. Print f['NEIGHBORS] for a few of your features and see what is printed. Also do print(type(f['NEIGHBORS'])) and see what is returned.
    – Ben W
    Feb 2, 2022 at 22:16
  • 1
    @ Ben W with the following command: 'layer = iface.activeLayer() for f in layer.getFeatures(): print(f['NEIGHBORS']) returns: 51,262 NULL 311 NULL 215 234,371 234 45 100 with the command layer = iface.activeLayer() for f in layer.getFeatures(): print(type(f['NEIGHBORS'])) returns: <class 'str'> <class 'PyQt5.QtCore.QVariant'> <class 'str'> <class 'PyQt5.QtCore.QVariant'> <class 'str'> <class 'str'> <class 'str'> <class 'str'> <class 'str'> <class 'str'> ...'
    – fcka
    Feb 2, 2022 at 23:05
  • 1
    @ Ben W Yes of course
    – fcka
    Feb 3, 2022 at 22:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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