0

In the QGIS User interface, it is possible to view the Attribute Table for all the features of a Vector Layer.

Is there a way to directly read and write the Attribute Table in the Python API?

I searched for a long time and could not find it. I can create a table (pandas df) through iteration, but do not know if that is a good practice.

import pandas as pd

attribute_table = list()
for z in zip_code_layer.getFeatures():
    attrib = z.attributes()
    attribute_table.append(attrib)

headers = zip_code_layer.fields().names()

attribute_df = pd.DataFrame(attribute_table, columns = headers)
attribute_df.Zip_Code = attribute_df.Zip_Code.astype('int64')

My aim is to create additional columns to, or edit existing values in the pandas dataframe, attribute_df, and then write it back to the vector layer.

I know I can awkwardly extend the number of attributes, and update features one at a time, but I can't help thinking there has to be a better way.

4
  • You can refer to this question and answers to see how to write an attribute table from a dataframe a row at a time using a loop.
    – Matt
    Oct 14 at 15:30
  • This illustrates the problem I am having with the Python API. At the vector layer level there should be methods called getAttributes() and setAttributes() that mimic what I can do using the UI and attribute table. But there doesn't seem to be any. It makes no sense to me that functions provided by the UI cannot be easily accomplished in the API. Oct 14 at 19:25
  • Matt, this is not an answer to my question. The looping construct creates new features. I want to update the attributes of existing features. Oct 14 at 19:59
  • Indeed, so you could adapt the code to fit your use case. Instead of creating a feature, you could get the existing features of the layer and iterate them.
    – Matt
    Oct 15 at 12:21
1

You don't need panda at all to manipulate your data.

Take a look in the docs of PyQGIS API and you will find this method of QgsVectorLayer.

So a minimal example to add an attribute:

layer = iface.activeLayer()  # layer is a QgsVectorLayer instance, no matter how we get it.
layer.startEditing()  # needed  to allow you to perform changes on the layer
layer.addAttribute(QgsField('toto', QVariant.String))  # here you can customize the arguments as you like (see the docs)
layer.commitChanges()  # to make your changes permanent at the provider level

To get the existing attributes of a QgsVectorLayer:

fields = layer.fields()
for field in fields:
    print(field.name())

to access specific value of an attribute:

for feature in layer.getFeatures():
    print(feature['attribute_name']) # will print the value of attribute_name for each feature of your QgsVectorLayer

to edit attribute values:

layer.startEditing()
for feat in layer.getFeatures():
    new_value = 'titi'
    layer.changeAttributeValue(feat.id(), 2, new_value)  # 2 is the index of the field you want to update 
layer.commitChanges()
4
  • Thank you for confirming my suspicion that there are no methods for accessing the attribute table as a single python object. The techniques you provided will be helpful to me. Missing from my question (which I omitted because it would cloud the issue) is that I plan to import numeric data from a file. Which subsequently is joined with attribute table data using Pandas, and new columns calculated. I have already successfully done this. All that remains is linking the Pandas table with the Feature objects to change the correct features. Oct 15 at 11:38
  • Actually, the attribute table in QGIS is a Qt View (QgsAttributeTableView) displaying datas of a QgsVectorLayer with a Qt Model (QgsAttributeTableModel). Search how Qt use MV(C) to handle complex Ui if you want to dig more deeply. For your question you need to a key to join your pd datas to the feature of your layer and you're good I guess.
    – YoLecomte
    Oct 15 at 15:48
  • I joined on the zipcode value that was in both tables and that worked fine. Was able to convert and write to the attribute table. For my final trick, I will update the display of the vector layer based on the new field that as inserted in the attribute table. This will require some research. Oct 15 at 16:30
  • Good news! For your styling concern, you will find a lot of resources over the internet.
    – YoLecomte
    Oct 17 at 7:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.