11

I need to obtain, for each feature of a layer, a dictionary with the attribute names and their values using PyQGIS.

I can get all the attributes of the layer using:

from qgis.core import QgsProject

indiv = QgsProject.instance().mapLayersByName('Individuos')[0]

for feature in features:
    value = feature[field.name()]
    attrs = feature.attributes()
    print(attrs)

But what I need is to create a dictionary with field names as key and their value for each feature.

1
  • There's a bit of code between indiv= and for feature in features: that you've not shown. One line to get features from the layer and another to get field, or better still all the field names.
    – Spacedman
    Commented Sep 16, 2020 at 10:09

5 Answers 5

16

The QgsJsonUtils class has exportAttributes method for getting attributes as a dict.

Solution 1:

Making a dictionary including feature "id" as key, attributes map as value:

{feature1.id: {attr1: value, attr2: value, ...},
 feature2.id: {attr1: value, attr2: value, ...},
 ...}
from qgis.core import QgsProject

layer = QgsProject.instance().mapLayersByName('LAYER_NAME')[0]

features_dict = {f.id(): QgsJsonUtils.exportAttributes(f) for f in layer.getFeatures()}

Solution 2:

Making a list including attributes map (dict) of features:

[{attr1: value, attr2: value, ...}, # feature 1
 {attr1: value, attr2: value, ...}, # feature 2
 ...]
from qgis.core import QgsProject

layer = QgsProject.instance().mapLayersByName('LAYER_NAME')[0]

features_list = [QgsJsonUtils.exportAttributes(f) for f in layer.getFeatures()]
1
  • Your solution 1 is perfect for what I'm looking. Thanks as always. Commented Sep 16, 2020 at 11:11
11

The snippet below should help you. It just prints a dictionary for each feature to the console, but you could do something else with the feature attribute dictionaries if you wanted.

from qgis.utils import iface

layer = iface.activeLayer()

def print_atts_dict(layer, feature):
    flds = [f for f in layer.fields()]
    atts = {}
    for f in flds:
        atts[f.name()] = feature[f.name()]
    print(atts)
    
for f in layer.getFeatures():
    print_atts_dict(layer, f)
5

The easiest way is using the underdog __geo_interface__, that was defined by Sean Gillies at https://gist.github.com/sgillies/2217756:

layer = iface.activeLayer()
    
for feature in layer.getFeatures():
    attributes = feature.__geo_interface__["properties"]
    print(attributes)

References:

5
# get the fields and features:
fields = indiv.fields()
features = indiv.getFeatures()

# initialise an empty dict with each field name:
attdict = {}
for field in fields:
    attdict[field.name()] = []

# for each field in each feature, append the relevant field data to the dict item:
for feature in features:
  for field in fields:
    v = feature[field.name()]
    attdict[field.name()].append(v)

print(attdict)

That gives a dict that looks like this for some Ghana regions:

{'shapeName': ['Greater Accra', 'Central', 'Western', 'Eastern', 'Ashanti', 'Volta', 'Brong Ahafo', 'Northern', 'Upper West', 'Upper East'],
 'shapeISO': ['GH-AA', 'GH-CP', 'GH-WP', 'GH-EP', 'GH-AH', 'GH-TV', 'GH-BA', 'GH-NP', 'GH-UW', 'GH-UE'],
 'shapeID': ['GHA-ADM1-1590546715-B1', 'GHA-ADM1-1590546715-B2', 'GHA-ADM1-1590546715-B3', 'GHA-ADM1-1590546715-B4', 'GHA-ADM1-1590546715-B5', 'GHA-ADM1-1590546715-B6', 'GHA-ADM1-1590546715-B7', 'GHA-ADM1-1590546715-B8', 'GHA-ADM1-1590546715-B9', 'GHA-ADM1-1590546715-B10'],
 'shapeGroup': ['GHA', 'GHA', 'GHA', 'GHA', 'GHA', 'GHA', 'GHA', 'GHA', 'GHA', 'GHA'], 'shapeType': ['ADM1', 'ADM1', 'ADM1', 'ADM1', 'ADM1', 'ADM1', 'ADM1', 'ADM1', 'ADM1', 'ADM1']}

Which I think is what you are after.

2

Another solution utilizes the attributeMap() method of the QgsFeature class.

Returns the feature's attributes as a map of the field name to value.

from qgis.utils import iface
from PyQt5.QtCore import QDate

layer = iface.activeLayer()

for feat in layer.getFeatures():
    attributes = feat.attributeMap()
    attributes_ = {key : value if not isinstance(value, QDate) else value.toString("dd.MM.yyyy") for key, value in attributes.items()}
    print(feat.id(), attributes_)

That results into:

0 {'ColumnA': '1, Michigan Street, Michigan', 'ColumnB': 'Michigan Street', 'ColumnC': '01.05.2023', 'id': 1, 'integer': NULL, 'real': 15.15, 'string': 'Some Text', 'trouble': 'a'}
1 {'ColumnA': NULL, 'ColumnB': NULL, 'ColumnC': '30.04.2023', 'id': 2, 'integer': 100, 'real': NULL, 'string': 'Some Text', 'trouble': 'b'}
2 {'ColumnA': NULL, 'ColumnB': NULL, 'ColumnC': '02.05.2023', 'id': 3, 'integer': 100, 'real': 5.25, 'string': NULL, 'trouble': 'c'}
3 {'ColumnA': NULL, 'ColumnB': NULL, 'ColumnC': NULL, 'id': 4, 'integer': NULL, 'real': NULL, 'string': NULL, 'trouble': 'd'}
4 {'ColumnA': NULL, 'ColumnB': NULL, 'ColumnC': '03.05.2023', 'id': 5, 'integer': NULL, 'real': 10.1, 'string': 'Some Text', 'trouble': 'e'}

Note: There was performed one more additional step due to the type of an attribute - QDate() class which will appear as PyQt5.QtCore.QDate(2023, 5, 3) when one simply applies the feat.attributeMap().

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.