How to merge multiple vector layers in QGIS from a folder using Python

In this task we will select all the shapefiles in a folder and use python scripting to merge them with their attributes in a memory layer. The Processing algorithm Merge vector layers does the same thing, but we want to do it using Python.

The script is similar to that proposed in a previous task, but this time we don’t want to load the shapefiles in the Layers Panel before merging them.

We will use the datasets available from DIVA-GIS. First of all, download the administrative areas shapefiles for France, Germany and Switzerland; then, copy the shapefiles that will be merged in an external folder (in this task, for each country we will use the shapefile with “adm0” as final part of the filename which represents the boundaries of the country itself):

folder

The following code does the work (if you don’t know how to create a custom script, please see here):

from qgis.core import *
import os

# Set the directory where the input files are stored
directory = "C:/.../input_folder/"

# Get the list of input files
fileList = os.listdir(directory)

# Copy the features from all the files in a new list
feats = []
for file in fileList:
    if file.endswith('.shp'):
        layer = QgsVectorLayer(directory + file, file, 'ogr')
        for feat in layer.getFeatures():
            geom = feat.geometry()
            attrs = feat.attributes()
            feature = QgsFeature()
            feature.setGeometry(geom)
            feature.setAttributes(attrs)
            feats.append(feature)

# Get the Coordinate Reference System and the list of fields from the last input file
crs = layer.crs().toWkt()
field_list = layer.dataProvider().fields().toList()

# Create the merged layer by checking the geometry type of  the input files (for other types, please see the API documentation)
if layer.wkbType()==QGis.WKBPoint:
    v_layer = QgsVectorLayer('Point?crs=' + crs, 'Merged', "memory")
if layer.wkbType()==QGis.WKBLineString:
    v_layer = QgsVectorLayer('LineString?crs=' + crs, 'Merged', "memory")
if layer.wkbType()==QGis.WKBPolygon:
    v_layer = QgsVectorLayer('Polygon?crs=' + crs, 'Merged', "memory")

# Add the features to the merged layer
prov = v_layer.dataProvider()
prov.addAttributes(field_list)
v_layer.updateFields()
v_layer.startEditing()
prov.addFeatures(feats)
v_layer.commitChanges()

QgsMapLayerRegistry.instance().addMapLayer(v_layer)

This will be the result:

merged

You can save the merged vector layer by right clicking on its name in the Layers Panel and then by clicking “Save as…”.

We need to make some remarks:

  1. the above code works for shapefiles that have same fields and the same type of geometry;
  2. the code checks for the most common geometry types (point, line, polygon) of the input layers before creating the merged shapefile. For other geometry types, please replace the lines 28-33 with proper (but similar) syntax taken from the QGIS API Documentation.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s