Monday 27 November 2017

pyqgis - What are QGIS equivalent functions for ArcPy's Update/Delete Row/Field?


I am trying to reprogram some scripts from ArcPy to QGIS (1.8 or 2.0) and there are some simple functions that I want to be able to redo but unfortunately documentation in QGIS is lacking in certain areas.


Namely the three most important for me are:


Add Field - Add field


arcpy.AddField_management(Feature, "ID", "SHORT")


Calculate Field Management - Update that field


arcpy.CalculateField_management(Feature,"ID","!FID!")

Update/Delete Rows - Update/Delete rows based on condition (without copying the shapefile)


keep = ["Bob","Janet","John","Mike"]
Counter = 0
rows = arcpy.UpdateCursor(Feature)

for row in rows:
if row.Name in keep:

row.ID = Counter
rows.updateRow(row)
else:
rows.deleteRow(row)
Counter += 1

Now I can iterate through each feature in QGIS using SEXTANTE and obtain its geometry which I should be able to rewrite into a new shapefile and thereby update/delete a row or field. Starting with something along the lines of...


layer = st.getobject(Polygon)
features = st.getfeatures(layer)
for f in features:

f.geometry().asPolygon()

but I can't find a simple solution for those functions mentioned above?



Answer



The following examples are based on the (soon-to-be-released) QGIS 2.0 API. This has changed since 1.8, so the syntax for this version will differ in some places.


The best resource for 1.8 compliant solutions and in-depth explanation for background of parameters (also apply for 2.0) are the PyQGIS Cookbook


We'll assume you already have a reference to a vector layer called vl obtained by e.g.


vl = iface.activeLayer()

Transactions



The following examples are working in a transaction (locally cached in QGIS). Before starting the edit session you have to call


vl.startEditing()

and end it with


vl.commitChanges()

to write your changes to the data source. or


vl.rollBack()

to dismiss the changes



You could also work directly on vl.dataProvider() and forget about the transaction control statements. (Resulting in autocommit-like behaviour)


Adding a field


QgsVectorLayer.addAttribute( QgsField )


from PyQt4.QtCore import QVariant
vl.addAttribute( QgsField( 'fieldname', QVariant.String ) )

This only works, if the dataprovider implements the AddAttributes capability. You can check this with:


if vl.dataProvider().capabilities() & QgsVectorDataProvider.ChangeAttributeValues

Calculate fields



See this answer:


Is it possible to programmatically add calculated fields?


It's still aimed at 1.8, so instead of vl.select() you have to call the 2.0 equivalent vl.getFeatures() ( see QGIS API changes )


Update rows


QgsVectorLayer.updateField( featureId, fieldIndex, value )


vl.updateField( 1000, 5, 'hello' )

Preqrequisites check (optional):


if vl.dataProvider().capabilities() & QgsVectorDataProvider.ChangeAttributeValues


To know the fieldIndex, you can use QgsVectorLayer.pendingFields()


Edit: See also the comment by NathanW which mentions the well readable QgsVectorLayer.updateFeature( feature ) method.


Delete rows


QgsVectorLayer.deleteFeature( featureId )


vl.deleteFeature( 1000 )

Optional prerequisites check:


if vl.dataProvider().capabilities() & QgsVectorDataProvider.DeleteFeatures

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...