[GIS] Save a layer for each unique value using Python in QGIS

layerspyqgispythonqgis

I have a map, in which each region is defined as an attribute of the map (I can select each region from the attribute table). I am trying to create new layers each one containing only 1 region using Python (quite like the gui command " save selection as..").

I have got so far (I am very new to Python, so forgive all the obvious errors I have made here):

from qgis.core import *
from qgis.gui import *
layer_Map = canvas.layer(0) #select the layer
provider = layer_Map.dataProvider()
fields = provider.fields()

writer = QgsVectorFileWriter("P:\Qgis\Output\Writer.shp", "CP1250", fields,provider.geometryType(), provider.crs(), "ESRI Shapefile")

Selection = layer_Map.select(1) #This selects the region of the map I want to write in the new layer

writer.addFeature(Selection) #this is clearly wrong, as I get an error

Best Answer

Try the Unique_values_saver plugin for QGIS. It allows you to save one vector layer for each unique value from a specific field.

enter image description here

For instance, for a layer with world countries and regions, I've generated 10 vector layers, each one corresponding to a different region.

enter image description here

If you need the way to do it in Python, just have a look at the source code of the plugin, specifically at the uniqueValues method:

# copyright            : (C) 2014 by Giuseppe De Marco
# email                : info@pienocampo.it
# Snippet taken from the Unique_values_saver QGIS plugin
def uniquevalues (self):
    self.dlg.ui.txt.clear()
    lay = self.choose_layer()
    fie = self.choose_field()
    uniquevalues = []
    progress = self.dlg.ui.progressbar
    progress.setValue(0)
    if ((lay != "") and (fie != "")):
        for name, layer in QgsMapLayerRegistry.instance().mapLayers().iteritems():
            if layer.name() == lay:
                uniqueprovider = layer.dataProvider()
                fields = uniqueprovider.fields()
                dir = self.get_dir()
                if dir==None:
                    QMessageBox.information(None, "Shapesaver","No output directory given: aborting...")
                    return
                else:
                    QMessageBox.information(None, "Shapesaver","output dir : "+str(dir))
                    for field in fields:
                        if field.name() == fie:
                            id = fields.indexFromName(fie)
                            uniquevalues=uniqueprovider.uniqueValues(id)
                            progress.setMaximum(len(uniquevalues))
                            if uniquevalues:
                                for uv in uniquevalues:
                                    progress.setValue(progress.value()+1)
                                    for field in fields:
                                        if field.name() == fie:
                                            selectList =[]
                                            for f in layer.getFeatures():
                                                attrs = f.attributes()
                                                double = ""#checks for duplicates in case of null attr value
                                                for attr in attrs:
                                                    if str(attr) == str(uv):
                                                        if str(f)!= str(double):#checks for duplicates in case of null attr value
                                                            selectList.append(f.id())
                                                            double = f 
                                            # writes matching features in a new shapefile
                                            if selectList:
                                            #selectlayer.setSelectedFeatures(selectList)
                                                savname = field.name()+str(uv)+".shp"
                                                savename = os.path.join(dir, savname)
                                                self.dlg.ui.txt.append("Saving "+str(savename))
                                                if len(savename) <= 0:
                                                    QMessageBox.information(None, "Shapesaver","No output filename given")
                                                    return
                                                else:
                                                    outfile = QgsVectorFileWriter(savename, "utf-8", fields, uniqueprovider.geometryType(), uniqueprovider.crs())
                                                    for i in range(len(selectList)):
                                                        for sf in layer.getFeatures():
                                                            if sf.id() == selectList[i]:
                                                                attributes = sf.attributes()
                                                                geometry = sf.geometry()
                                                                feature = QgsFeature()
                                                                feature.setAttributes(attributes)
                                                                feature.setGeometry(geometry)
                                                                outfile.addFeature(feature)
                                                selectList =[]
    return
Related Question