I am working in pygis for QGIS and have a problem regarding the attribute table and its values. I can create the new attribute table just fine but cannot add any values to it. I am new to pygis and not quiet sure what I am doing wrong. Someone in another forum suggested that the use of dataProvider()-methods with layer editing might cause the bug, but I am still not sure how to fix it.
part with the problem:
output_lyr.startEditing()
output_lyr.addAttribute(QgsField('EW_new', QVariant.Double))
output_lyr.updateFields()
output_lyr.commitChanges()
# ...
# Annahme: Der Vektorlayer "FPG_count" wurde bereits erstellt, und das Feld "EW_new" ist vorhanden.
# Iteriere durch die GEB_ID-Listen und berechne EW_new-Werte
for geb_id, feature_ids in geb_id_lists.items():
num_elements = len(feature_ids)
# Überprüfen, ob die GEB_ID im Dictionary "geb_id_to_ew" existiert
if geb_id in geb_id_to_ew:
ew_value = geb_id_to_ew[geb_id]
# Überprüfen, ob "EW" nicht 0 ist, bevor die Berechnung ausgeführt wird
if num_elements != 0:
result = ew_value / num_elements
# Den berechneten Wert in das Feld "EW_new" schreiben
for feature_id in feature_ids:
output_lyr.dataProvider().changeAttributeValues({feature_id: {output_lyr.fields().indexFromName('EW_new'): result}})
output_lyr.updateExtents()
else:
# Wenn num_elements gleich 0 ist, wird ein Platzhalterwert eingefügt
for feature_id in feature_ids:
output_lyr.dataProvider().changeAttributeValues({feature_id: {output_lyr.fields().indexFromName('EW_new'): 0}})
Full code
# Lädt alle notwendigen Bibliotheken (libaries) in das Skript
from qgis.core import QgsProject, QgsVectorLayer, QgsVectorFileWriter, QgsField
from PyQt5.QtCore import QVariant
#Greift auf das aktuelle GIS Projekt zu
project = QgsProject.instance()
#Definiert Namen in Python für die jeweiligen Layer im Projekt.
fpg = project.mapLayersByName('FPG_cut')[0]
wgf = project.mapLayersByName('WGF_cut')[0]
output_lyr = QgsVectorLayer(f'Point?crs={fpg.crs().authid()}', 'FPG_count', 'memory')
output_lyr.dataProvider().addAttributes(fpg.fields())
output_lyr.updateFields()
# Feld das gesammelt werden soll
field_name = 'GEB_ID'
# Python dictionary um die IDs zu sammeln
geb_id_lists = {}
# Iteriert durch die features des Punkte Layers
for feature in fpg.getFeatures():
geb_id = feature[field_name]
if geb_id not in geb_id_lists:
geb_id_lists[geb_id] = []
geb_id_lists[geb_id].append(feature.id())
# Zähle und drucke die Anzahl der Listen
print(f"Number of unique 'GEB_ID' lists: {len(geb_id_lists)}")
# Sortieren und Filtern jeder Liste nach den Feldern "LDEN", "VAR" und "FPG".
for geb_id, feature_ids in geb_id_lists.items():
# Sortieren nach dem Feld "LDEN" in absteigender Reihenfolge - buggy
sorted_feature_ids = sorted(feature_ids, key=lambda id: fpg.getFeature(id)['LDEN'], reverse=False)
# Filter nach "VAR"-Feld (nur "+" behalten) und "FPG"-Feld (nur "Wohngeb" behalten)
filtered_feature_ids = [id for id in sorted_feature_ids if fpg.getFeature(id)['VAR'] == '+' and fpg.getFeature(id)['FPG'] == 'Wohngeb']
geb_id_lists[geb_id] = filtered_feature_ids
# Feststellen, ob die Anzahl der Werte gerade oder ungerade ist
for geb_id, feature_ids in geb_id_lists.items():
count = len(feature_ids)
if count % 2 == 1: # Wenn die Anzahl ungerade ist, wird der kleinste Wert entfernt. Hier der erste Wert weil die Liste mit den kleinsten Werten beginnt.
feature_ids.remove(geb_id_lists[geb_id][0])
# Entfernen Sie die untere Hälfte der Werte aus jeder Liste.
for geb_id, feature_ids in geb_id_lists.items():
count = len(feature_ids)
if count > 1: # Mindestens ein Wert bleibt in der Liste
half_index = count // 2
geb_id_lists[geb_id] = feature_ids[half_index:]
# Verteilung der Bewohner auf die verbleibende größere Hälfte des Hauses
# Annahme: Der Vektorlayer "FPG_count" wurde bereits erstellt, und das Feld "EW_new" ist vorhanden.
output_lyr.startEditing()
output_lyr.addAttribute(QgsField('EW_new', QVariant.Double))
output_lyr.updateFields()
output_lyr.commitChanges()
# ...
# Iteriere durch die GEB_ID-Listen und berechne EW_new-Werte
for geb_id, feature_ids in geb_id_lists.items():
num_elements = len(feature_ids)
# Überprüfen, ob die GEB_ID im Dictionary "geb_id_to_ew" existiert
if geb_id in geb_id_to_ew:
ew_value = geb_id_to_ew[geb_id]
# Überprüfen, ob "EW" nicht 0 ist, bevor die Berechnung ausgeführt wird
if num_elements != 0:
result = ew_value / num_elements
# Den berechneten Wert in das Feld "EW_new" schreiben
for feature_id in feature_ids:
output_lyr.dataProvider().changeAttributeValues({feature_id: {output_lyr.fields().indexFromName('EW_new'): result}})
output_lyr.updateExtents()
else:
# Wenn num_elements gleich 0 ist, wird ein Platzhalterwert eingefügt
for feature_id in feature_ids:
output_lyr.dataProvider().changeAttributeValues({feature_id: {output_lyr.fields().indexFromName('EW_new'): 0}})
sum_result = sum(result_values)
# ...
# Grenzwert
threshold_lden = 55
# Punkte mit "LDEN"-Werten unterhalb des Schwellenwerts herausfiltern
for geb_id, feature_ids in geb_id_lists.items():
feature_ids = [id for id in feature_ids if fpg.getFeature(id)['LDEN'] >= threshold_lden]
geb_id_lists[geb_id] = feature_ids
# Fügen Sie die Merkmale zur Ergebnisebene hinzu.
for geb_id, feature_ids in geb_id_lists.items():
for feature_id in feature_ids:
output_lyr.dataProvider().addFeatures([fpg.getFeature(feature_id)])
# Berechnen Sie die Gesamtzahl der Punkte in der Ausgabeschicht.
num_points_output_layer = output_lyr.featureCount()
# Druckt die Gesamtzahl der Punkte
print(f"Total number of points in the output layer: {num_points_output_layer}")
project.addMapLayer(output_lyr)
# Aktualisiert die Karte
iface.mapCanvas().refreshAllLayers()
I tried deleting the "output_lyr.commitChanges()" lines and adding a lines like output_lyr.updateFeature(feature), but it does not seem to update or add the values to my new attribute field.