8

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?

  • I'm not quite sure, what the aim of the last part of your question is. Why do you mention SEXTANTE? You ask for a method to rewrite into a new shapefile, but your code excerpt does nothing such afaics. – Matthias Kuhn Jul 29 '13 at 10:53
  • Thanks Matthias - I originally showed the SEXTANTE as a good way for myself to share my scripts. Initially I tried to make a plugin but found that the automatic gui generation in the SEXTANTE was a better way to get user input to a script - similar to arctoolbox - i should of explained that clearer.... – BJEBN Jul 29 '13 at 12:27
16

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
  • 2
    Using feature[5] = 'hello' and layer.updateFeature(feature) is better then using vl.updateField IMO – Nathan W Jul 29 '13 at 12:30
  • Thanks Matthias - thats exactly what I needed to get me started. I do find however that QGIS is more verbose in general than arcpy... – BJEBN Jul 29 '13 at 12:31
5

This is how you would do your code in PyQGIS:

keep = ["Bob","Janet","John","Mike"]

for counter, feature in enumerate(layer.getFeatures()):
    if feature['Name'] in keep:
        feature['ID'] = counter
        layer.updateFeature(feature)
    else:
        layer.deleteFeature(feature.id())
1

Check out PyQGIS cookbook and vector layer modification section in particular.

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.