You may try running the code below in the python console in QGIS 3. There may be a more elegant way to code this task, but I tried it on a small test data set and it did work (quickly), however I am not convinced it would be faster than @Kazuhito's solution using a native field calculator expression. I will be interested to hear how it goes if you try it on your full data set. Note: I have included a progress dialog with a cancel button which should allow you to break out of the main for loop if it is taking too long. Hint: This could also be implemented in a background thread using QgsTask if necessary; or better still, put into a script for the processing toolbox since they are automatically run in a background thread where possible. There are some useful templates and tutorials for QGIS 3 processing scripts, so you would need to make an attempt at some code by yourself then post a new question if you get stuck.
Also: It seems the name of your layer is 'MT'. If that is not the case, please change the layer name string in the first line below to match yours (double check the field names in my script match yours too).
layer = QgsProject().instance().mapLayersByName('MT')[0]
fld_idx2 = layer.fields().lookupField('ITID')
fld_idx3 = layer.fields().lookupField('class1')
feats = [feat for feat in layer.getFeatures()]
itids = []
for feat in feats:
itids.append(feat.attributes()[fld_idx2])
itid_vals = set(itids)
min_group_lists = []
v_count = len(itid_vals)
prog = QProgressDialog('Working...', 'Cancel', 0, 100)
prog.setWindowModality(Qt.WindowModal)
prog.setMinimumDuration(1)
check_value = 1
for current, val in enumerate(itid_vals):
f = int(current + 1)
pcnt = int(f/v_count * 100/1)
prog.setValue(pcnt)
if prog.wasCanceled():
iface.messageBar().pushMessage('Info', 'Action Cancelled', level=Qgis.Info)
break
check_value = 0
group = {}
for feat in feats:
cls1 = feat.attributes()[fld_idx3]
if feat.attributes()[fld_idx2] == val:
group[feat.id()] = cls1
n_min = min(group.values())
min_group_lists.append([k for k, v in group.items() if v == n_min])
all_min_ids = []
for l in min_group_lists:
all_min_ids.append(l[0])
if check_value == 1:
feats_to_update = layer.getFeatures(all_min_ids)
fld_ID = layer.fields().lookupField('ITID_1')
for f in feats_to_update:
fld_val = f.attributes()[fld_idx2]
atts = {fld_ID: fld_val}
layer.dataProvider().changeAttributeValues({f.id(): atts})
Here is the attribute table of my test subset of data after running the code:
