I'm trying to replicate a nearest-neighbor analysis that returns X (one OR more than one) neighbors in either QGIS or PyQGIS.

For example: enter image description here

In this output, I have a set of locations (Red Stars) that are being connected to the target hubs (Blue Circles) via nearest neighbor analysis (Pink Lines). What I'd like is to find the 2nd, 3rd, 4th, etc. nearest neighbor for my set of locations to relate to hubs.

Many methods are available for performing this in PostGIS and in ArcGIS/ArcPy but it seems like there isn't an explicit method for returning more than one neighbor using Distance to Hubs or the NNJoin plugin.

Ideally, the best method would be either PyQGIS/Python based or easily replicable via the QGIS modeler interface.

Some other examples from the net:

How to get the second nearest neighbor between two point patterns in R?

Indexed Nearest Neighbour Search in PostGIS

  • I'm trying to clarify more by adding screenshots and examples. Not sure what isn't clear. Commented Jan 31, 2018 at 21:21
  • 2
    Have you tried using the Distance matrix tool? This calculates distances from each point to every other point and saves it into a .csv file. You could then sort it using spreadsheet software or the Group Stats plugin to find x number of closest neighbours.
    – Joseph
    Commented Feb 1, 2018 at 10:28

2 Answers 2


Following Joseph's suggestion, the answer lies in performing a distance matrix calculation using the PyQGIS algorithm designed for it. From here you can determine K-nearest neighbours and return a table of results. Exactly what I needed for my purposes.


The tool you are looking for has been introduced in QGIS 3.8: join attributes by nearest. It can be found in processing toolbox.

enter image description here

It joins a layer with the x nearest neighbour's attributes and adds the distance as well as coordinates. The input layers features will be x times duplicated.

If you wish to additionally connect them by lines afterwards, you could do it for example with geometry by expression on the just joined layer like this:

make_line($geometry, geometry(get_feature_by_id('LayerName Of InputLayer2 From JoinByNearest',"JoinedIdFieldName")))
  • Oh wow. That's good to know! I still need to perform these types of operations from time to time. Thanks for mentioning it! Commented Apr 21, 2020 at 17:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.