PyQGIS: Perform a Spatial Join with the QGIS Python API


Just as spatial joins can be performed in QGIS with the Join Attributes by Nearest tool, the QGIS Python API (PyQGIS) can be used to perform spatial joins in the same manner. This article will demonstrate, with code, how to perform a spatial join with PyQGIS.

This example will join the attributes of a line feature nearest to a point feature. The result will be a new point layer that includes attributes from the original point and from the nearest line feature.

In addition to the Join Attributes by Nearest too, spatial joins can also be conducted with the Join Attributes by Location tool. The video at the end of the post demonstrates how to perform both operations.

Specify File Paths

Start by specifying the paths to the input and output files. Here, I’m using point (fnpts) and lines (fnlines) shapefiles as the inputs. The output will be a point shapefile (fnout). You can save the output to memory by specifying "memory" instead of a file path.

fnpts = 'points.shp'
fnlines = 'lines.shp'
fnout = 'nearestjoin.shp'

Setup the Input Dicitionary

Once the input and output file paths are specified you can set up the dictionary input to the processing algorithm. This is quite simple to do. The input dictionary give the tool all the same parameters you would give it if you were running it from the QGIS GUI.

You can use processing.algorithmHelp("native:joinbynearest") to see the help documentation for calling the tool and to see what the values for the input dictionary are. Additionally, I explained each of the input parameters in detail in an article about spatial joins in QGIS. I recommend reviewing this article if you are unsure what the inputs represent. Examples of this, and other, processing algorithms with data included are available in my full PyQGIS course.

Input dictionary:

idict = {'INPUT':fnpts,\
'INPUT_2':fnlines,\
'FIELDS_TO_COPY':[],\
'DISCARD_NONMATCHING':True,\
'PREFIX':,\
'NEIGHBORS':1,\
'MAX_DISTANCE':,\
'OUTPUT':fnout}

Call the Processing Function

Once the input dictionary is set up, all we need to do is call the processing algorithm and pass it the input dictionary. This is done with a call to processing.run that passes in the name of the processing algorithm as a string ("native:joinbynearest") and the input dictionary (idict).

processing.run("native:joinbynearest", idict)

After execution of this code the output file will be available at the output location.

Add the New Layer to the QGIS Interface

Finally, you will probably want to add the newly created layer to the QGIS interface so that you can view your results. This is easily done in a single line of code. All you need is the output file name so you can add the vector layer to the interface.

iface.addVectorLayer(fnout, '', 'ogr')

Full Code Block

The full code is presented in the script below. Note, this code does not save the input dictionary as a variable. Instead, a full dictionary is passed directly the processing.run call.

fnpts = 'points.shp'
fnlines = 'lines.shp'
fnout = 'nearestjoin.shp'

processing.run("native:joinbynearest",\
{'INPUT':fnpts,\
'INPUT_2':fnlines,\
'FIELDS_TO_COPY':[],\
'DISCARD_NONMATCHING':True,\
'PREFIX':,\
'NEIGHBORS':1,\
'MAX_DISTANCE':,\
'OUTPUT':fnout})

iface.addVectorLayer(fnout, '', 'ogr')

Watch Video

Konrad Hafen

Konrad has a Master's Degree in Ecology and a Doctorate Degree in Water Resources and has been performing geospatial analysis and writing code (in multiple programming languages) for over a decade. He writes code to develop models and analysis workflows to predict and evaluate changes to landscapes and water resources. He has published multiple articles in prominent peer-reviewed, scientific journals. Konrad's code and workflow contribute to operational products that inform water and ecosystem management.

Latest Tutorials