4

I am very new to PyQgis.

I have a shapefile containing a lot of information for each place, it looks like this

id    stat_1   stat_2 ... stat_n
i1     0        0          2
i2     1        1          0
            ...
iT     0        0          2

I want to create n shapefiles, containing for each of them: id and sta_i and only the locations which statistic is not equal to 0. Something like:

id    stat_i   
i3     1    
ij     2       
            ...
iT     4

Doing this manually would be quite tedious, which is why I decided to get started with PyQgis. I figured out how to select my main layer and how to select the features I want ( I actually just figured out how to print them). How can I actually create a new shapefile with the subsetted locations and just the two desired fields? I will sort out how to loop over the fields later.

layer=None
fields=["id","stat_i"]

for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
    if lyr.name() == "Layer_Name"
        layer = lyr
        break

request=QgsFeatureRequest().setFilterExpression(u'"stat_i"!=0')
it=layer.getFeatures(request)
for feat in it :
        print feat.id()
4

I guess there is an easier way to select your layer, subset your data and save it :

lyr = QgsMapLayerRegistry.instance().mapLayersByName("Layer_name")[0]
lyr.setSubsetString("stat_i != 0") # You can unset it by using None 
QgsVectorFileWriter.writeAsVectorFormat(lyr, "my_subset.shp",
                                        "UTF8", None, "ESRI Shapefile")

And so on with the n shapefiles you have to write.

Edit : I missed up the part where you want to select specific fields. I guess you can try (and improve!) something like this :

lyr = QgsMapLayerRegistry.instance().mapLayersByName("Layer_name")[0]
# Lets say you have 10 fields 'stat_x':
for i in range(10):
    lyr.setSubsetString("stat_{} != 0".format(i))
    fields = QgsFields() # It will contain your new fields (name and type)
    field1, field2 = 'id', 'stat_{}'.format(i)
    [fields.append(fi) for fi
     in (QgsField(field1, QVariant.Int),QgsField(field2, QVariant.Int))]

    # Here the args for QgsVectorFileWriter will be : 
    # FileName, Encoding, fields, GeometryType, CRS
    # See also http://qgis.org/api/classQgsVectorFileWriter.html
    writer_obj = QgsVectorFileWriter(
        "my_subset_n{}.shp".format(i), None, fields,
        lyr.dataProvider().geometryType(), lyr.crs())

    for ft in lyr.getFeatures():  # Loop on the subseted features
        # Create a new feature for each original feature
        new_ft = QgsFeature()
        # Give it its geometry :
        new_ft.setGeometry(ft.geometry())
        # Only keep the 2 selected fields :
        new_ft.setAttributes([ft[field1], ft[field2]])
        # Add the feature to the writer, ie. your output shapefile :
        writer_obj.addFeature(fet)

    del writer_obj # Features are written when the writer is deleted

If you haven't seen it, there is some useful insights in the pyQGIS doc about vector layers

  • Thanks. Can you explain to me what the codes does with the writer, starting from writer_obj= I guess the idea is to create the shapefile "my_subset_n{}" now. But where is it saved? – Doon_Bogan Mar 1 '16 at 14:31
  • I had an extra question as well, is "{ }" the generic way to call a variable inside a string? – Doon_Bogan Mar 1 '16 at 14:49
  • @Doon_Bogan In this example it is saved in your current working directory (you can know it with the statement os.getcwd()) but you also can specify a full path like "/home/me/my_project/subset_n{}".format(i). And your right about the {}, it's the way to format a variable in a string (i.e. it only works with format()and there is other way to place a variable in a string). See the docs about string formating in python. I will edit my post and put some comments to better explain what is done. – mgc Mar 1 '16 at 19:52

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.