The closest processing algorithm I can find is Join Attributes by Nearest which lets you select a maximum number of nearest neighbours and an optional maximum distance. You could select the relevant field(s) to join in this process. Now you'll have a row for each relation, and you can use any method to aggregate data based on the unique ID of your first layer using SQL in Virtual Layers, or QGIS expressions, or the Statistics by Categories processing algorithm.
Step 1: Join nearest features
Let's say, for example, your base layer is Layer1, with an unique id
field. You want to join the field population
from Layer2.
Open the Join Attributes by Nearest processing algorithm, and for 'Input layer', put in Layer1; for 'Input layer 2', put in Layer2. Select population
under the 'Input Layer 2 fields to copy' section (click the three dots). Select whatever you want for maximum nearest neighbours and distance.
The resulting layer will have a row for each feature in Layer1 and its nearest n features from Layer2 (up to the max distance). Each row will have all the Layer1 fields (including id
) and the population
field from the nearest Layer2 feature along with some other details. There may be multiple instances of the same Layer1 feature if there were multiple Layer2 features matched. See the red circles in the image below.
Now, you want to group that data by the id
field so that for each unique id
value, you have an aggregate calculation of the population
field from the nearest Layer2 features.
Step 2 option 1: Aggregate joined features (simple)
One simple method is the Statistics by Category processing tool. Under 'Input vector layer' select the joined layer from the previous step. 'Field to calculate statistics on' will be population
from Layer2 (and make sure the data type is numeric). 'Field(s) with categories' will be your id
field from Layer1.
The resulting table will return all the aggregate statistics you want - count, unique, min/max, sum, mean, std, etc. Notice the features where the aggregated values are from 2 or more original features from the previous screenshot.
Step 2 option 2: Aggregate joined features (advanced)
Another more flexible option is the Aggregate processing tool which lets you select as many fields as you want and what kind of aggregate function you want with each field.
In the example below in addition to a sum of population
from Layer2, I also want to get an average and standard deviation for the cows
and planes
fields, and concatenate unique instances of the numeric ref
identifying field with ;
as a delimiter, all also from Layer2. While I'm at it I want to retain the number of features that matched (maximum of n
) and the average distance from source and target feature(s) (average of distance
), both fields generated from the Join Attributes by Nearest tool.
As above, aggregate by id
but also ensure you keep that in your list - as it's the field we're grouping by just use first_value
as the aggregate function.
Use the buttons on teh right to add or remove fields and reorder them, and the dropdown boxes to select your aggregate function. You can rename output field names too. And don't forget to set your output field type, length and precision appropriately.
You can also use expressions to transform your source data - in this case ref
was an integer field in Layer2 and couldn't be concatenated so I just used to_string()
to change it to a string.
Result - notice it returns more results than the simpler tool because even if there was null/blank data in the matching Layer2
feature it still returns something. (Like id
17)
Other options include SQL (SELECT id, max(population), max(someotherfield), max(someotherfield2), min(population),.... FROM joined_layer GROUP BY id
) or a plugin like Dissolve with stats, or a Python algorithm.
If you need to do this for lots of layers consider automating the two-step process with the Model builder in the Processing toolbox.