Adding consecutive unique ID starting from 1 for each distinct set of values
We can use arrays for that:
array_find(
array_agg(
$id,
"ReportID_2"
),
$id
) + 1
With array_agg
we have an array of all id grouped by the ReportID_2 values.
Then, array_find
gets the position of the current id in the previous array, starting with the position 0.
Finally, we add 1 to get the positions from 1.
Possible solution by means of PyQGIS.
Let's assume there is a point layer called "Layer_B"
with it's attribute table, see image below.
Case 1. When the new "id"
has to be assigned in a range of each attribute field (without grouping).
P.S. Many thanks to @J. Monticolo
Proceed with Plugins > Python Console > Show Editor
and paste the script below
from PyQt5.QtCore import QVariant
fieldname = "info" #a field which is used as an aggregating factor
newfieldname = "newid" #a new field that will maintain new ids
layer = iface.activeLayer()
idx = layer.dataProvider().fieldNameIndex(fieldname)
pr = layer.dataProvider()
pr.addAttributes([QgsField(newfieldname, QVariant.Int)])
layer.updateFields()
req = QgsFeatureRequest()
req = req.addOrderBy(fieldname)
attr_old = None
with edit(layer):
for feat in layer.getFeatures(req):
attr = feat.attributes()[idx]
if attr == attr_old:
i += 1
else:
i = 1
feat[newfieldname] = i
layer.updateFeature(feat)
attr_old = attr
Press Run script
and get the output that will look like
Case 2. When the new "id"
has to be assigned every time when the value in another attribute field change (with grouping).
Proceed with Plugins > Python Console > Show Editor
and paste the script below
from PyQt5.QtCore import QVariant
fieldname = "info" #a field which is used as an aggregating factor
newfieldname = "newid" #a new field that will maintain new ids
layer = iface.activeLayer()
idx = layer.dataProvider().fieldNameIndex(fieldname)
list_attributes = []
for feat in layer.getFeatures():
list_attributes.append(feat.attributes()[idx])
list_attributes = list(set(list_attributes))
dct = {list_attributes[i]: i + 1 for i in range(len(list_attributes))}
pr = layer.dataProvider()
pr.addAttributes([QgsField(newfieldname, QVariant.Int)])
layer.updateFields()
with edit(layer):
for feat in layer.getFeatures():
attr = feat.attributes()[idx]
for key, value in dct.items():
if attr == key:
feat[newfieldname] = value
layer.updateFeature(feat)
Press Run script
and get the output that will look like
References:
- Free and Open Source GIS Ramblings | PyQGIS 101: Using expressions to compute new field values
- QGIS Python Tutorial: How to Add/Delete Field and Updating Attribute Value
- PyQGIS developer cookbook
- How to read the attribute values using PyQGIS?