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.

Taras
  • 32,823
  • 4
  • 66
  • 137
Raúl Casado
  • 1,069
  • 7
  • 19
  • 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 Sep 16 '20 at 10:09

5 Answers5

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

Taras
  • 32,823
  • 4
  • 66
  • 137
Kadir Şahbaz
  • 76,800
  • 56
  • 247
  • 389
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)

Taras
  • 32,823
  • 4
  • 66
  • 137
Ben W
  • 21,426
  • 3
  • 15
  • 39
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.

Taras
  • 32,823
  • 4
  • 66
  • 137
Spacedman
  • 63,755
  • 5
  • 81
  • 115
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:

Taras
  • 32,823
  • 4
  • 66
  • 137
bugmenot123
  • 11,011
  • 3
  • 34
  • 69
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().

Taras
  • 32,823
  • 4
  • 66
  • 137