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
    Commented Feb 1, 2022 at 22:57
  • As per the help center please do not include chit chat like thanks within your posts.
    – PolyGeo
    Commented 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
    Commented 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
    Commented 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
    Commented 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
    Commented Feb 2, 2022 at 23:05
  • 1
    @ Ben W Yes of course
    – fcka
    Commented Feb 3, 2022 at 22:57

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