PYGIS: Creating new attribute table and adding values to it

126 views Asked by At

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.

0

There are 0 answers