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.
5 Answers 5
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()]
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)
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:
# 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.
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()
.
Explore related questions
See similar questions with these tags.