How to refer to another layer in the field calculator?

Spatial joins are available in the field calculator after installing the refFunctions plugin.

geomwithin(targetLayer,targetField)

Out of the box, field calculator does not support spatial joins across feature layers. But, if you have a look at NathanW's post on the function editor for qgis expressions you will be able to make out that we can script our own data interaction.

The following script will allow you to express what you're after. It works by iterating through all features on the polygon layer and if there is a spatial join, then reference tabular data from the specified column:

from qgis.core import *
from qgis.gui import *
from qgis.utils import iface

allfeatures = None
index = QgsSpatialIndex()
indexMade = 0
refLayer = None

@qgsfunction(args="auto", group='Custom')
def spatialJoinLookup(layerName, refColumn, defaultValue, geom, feature, parent):

    if geom is None:
        return defaultValue

    # globals so we don't create the index, refLayer more than once
    global allfeatures
    global index
    global indexMade
    global refLayer

    # Get the reference layer
    if refLayer is None:
        for layer in iface.mapCanvas().layers():
            if layerName == layer.name():
                refLayer = layer
                break
    if refLayer is None:
        raise Exception("Layer [" + layerName + "] not found")

    # Create the index if not exists
    if indexMade == 0:
        index = QgsSpatialIndex()
        allAttrs = layer.pendingAllAttributesList()
        layer.select(allAttrs)
        allfeatures = {feature.id(): feature for (feature) in refLayer.getFeatures()}
        for f in allfeatures.values():
            index.insertFeature(f)
        indexMade = 1

    # Use spatail index to find intersect 
    fid = None
    ids = index.intersects(geom.boundingBox())
    for id in ids:
        fid = id
        break # Only get the first match.
    if fid is not None:
        return allfeatures[fid].attribute(refColumn)

    # Default
    return defaultValue

Polygon Layer Example

Below is an example of a polygon layer that you might have. I've also created a corresponding point layer that you will see in the final image.

enter image description here

Expression Usage

Note, if you want to use a separate column you must change the second argument to match the column name in the polygon dataset. Example, you could use the 'AreaNumber' column, but would have to match the column type in the field calculator settings.

enter image description here

Result

You can see that the default column value has been applied where there is no spatial join, and the other's have matched the correct data. Note the script I've given will only join on the first match. You would need to create some other business logic if your polygons were overlapping.

enter image description here


It can be done in Field Calculator with function aggregate(). In point layer create new field with field calculator expression like this:

aggregate(
layer:= 'polygon_layer_name',
aggregate:='concatenate',
expression:=joining_field_name,
concatenator:=', ',
filter:=intersects($geometry, geometry(@parent))
)

Where layer is polygon layer name written like string, aggreagate is aggregate function (can be used also sum etc.), expression is field from values will be taken,concatenator is joining character string (have to be set, even in this case) and filter is filtering features based on expression (in this case interesects layer geometry with geometry of parent layer).

For more info check Aggregates QGIS documentation.

For automatic updates can be used virtual fields or you can set the expression as Default value in Attributes Form settings in Layer Properties (Attribute form setting documentation).

enter image description here