r-spatial / RQGIS3

GNU Lesser General Public License v3.0
69 stars 19 forks source link

Adding QGIS Plugin NNJoin? #5

Closed jannes-m closed 5 years ago

jannes-m commented 5 years ago

asked by Marco via email: Is it possible to make the plugin (NNJoin) available in RQGIS(3)?

jannes-m commented 5 years ago

Hey Marco, in theory, it is possible. And corresponding Pull request are welcome, however, I prefer not to include further plugins since it is hard enough to maintain just the processing toolbox. In most cases, another solution is already existing. So in your case, you could just use sf for finding the nearest neighbor (see https://github.com/r-spatial/sf/issues/990):

library(mapview)
library(sf)
data(breweries)
tmp = breweries[1:2, ]
# just slightly moving the feature
tmp[1:2, "geometry"] = tmp[1:2, "geometry"] + 0.0001
# and  now join the information from the closest feature
st_join(tmp, breweries, join = st_nearest_feature)

Or you can use a QGIS geoalgorithm, there are several ones available for doing nearest neighbor calculations (see below), here, I go with the QGIS geoalgorithm qgis:distancetonearesthubpoints:

library("RQGIS3")
#> Loading required package: reticulate
library("sf")
#> Linking to GEOS 3.7.1, GDAL 2.3.2, PROJ 5.2.0
library("mapview")
data(breweries)
tmp = breweries[1:2, ]
# just slightly moving the features
tmp[1:2, "geometry"] = tmp[1:2, "geometry"] + 0.0001
# find out which QGIS geoalgorithms are at our disposal for nearest neighbor computations

find_algorithms("nearest")
#> Assuming that your root path is '/usr'!
#> [1] "Grid (IDW with nearest neighbor searching)----------->gdal:gridinversedistancenearestneighbor" 
#> [2] "Grid (Nearest neighbor)------------------------------>gdal:gridnearestneighbor" 
#> [3] "Distance to nearest hub (line to hub)---------------->qgis:distancetonearesthublinetohub" 
#> [4] "Distance to nearest hub (points)--------------------->qgis:distancetonearesthubpoints" 
#> [5] "Concave hull (k-nearest neighbor)-------------------->qgis:knearestconcavehull" 
#> [6] "Nearest neighbour analysis--------------------------->qgis:nearestneighbouranalysis" 
#> [7] "K-nearest neighbours classification (opencv)--------->saga:knearestneighboursclassificationopencv"
#> [8] "Nearest neighbour------------------------------------>saga:nearestneighbour"
# let's find out how to use `qgis:distancetonearesthubpoints`
alg = "qgis:distancetonearesthubpoints"
get_usage(alg)
#> Distance to nearest hub (points) (qgis:distancetonearesthubpoints)
#> 
#> 
#> ----------------
#> Input parameters
#> ----------------
#> 
#> INPUT: Source points layer
#> 
#> Parameter type: QgsProcessingParameterFeatureSource
#> 
#> Accepted data types:
#> - str: layer ID
#> - str: layer name
#> - str: layer source
#> - QgsProcessingFeatureSourceDefinition
#> - QgsProperty
#> - QgsVectorLayer
#> 
#> HUBS: Destination hubs layer
#> 
#> Parameter type: QgsProcessingParameterFeatureSource
#> 
#> Accepted data types:
#> - str: layer ID
#> - str: layer name
#> - str: layer source
#> - QgsProcessingFeatureSourceDefinition
#> - QgsProperty
#> - QgsVectorLayer
#> 
#> FIELD: Hub layer name attribute
#> 
#> Parameter type: QgsProcessingParameterField
#> 
#> Accepted data types:
#> - str
#> - QgsProperty
#> 
#> UNIT: Measurement unit
#>#> Parameter type: QgsProcessingParameterEnum
#> 
#> Available values:
#> - 0: Meters
#> - 1: Feet
#> - 2: Miles
#> - 3: Kilometers
#> - 4: Layer units
#> 
#> Accepted data types:
#> - int
#> - str: as string representation of int
#> e.g. 1
#> - QgsProperty
#> 
#> OUTPUT: Hub distance
#> 
#> Parameter type: QgsProcessingParameterFeatureSink
#> 
#> Accepted data types:
#> - str: destination vector file
#> e.g. d:/test.shp
#> - str: memory: to store result in temporary memory layer
#> - str: using vector provider ID prefix and destination URI
#> e.g. postgres:... to store result in PostGIS table
#> - QgsProcessingOutputLayerDefinition
#> - QgsProperty
#> 
#> ----------------
#> Outputs
#> ----------------
#> 
#> OUTPUT: <QgsProcessingOutputVectorLayer>
#> Hub distance
# get the parameter-argument list
params = get_args_man(alg)
#> Choosing default values for following parameters:
#> UNIT: 0
#> See get_options('qgis:distancetonearesthubpoints') for all available options.
# specify the arguments
params$INPUT = tmp
params$HUBS = breweries
# distance in meters
params$UNIT = 0 # meters, see get_options(alg)
# add a specific field
params$FIELD = "brewery"
params$OUTPUT = file.path(tempdir(), "nearest.shp")
out = run_qgis(alg = alg, params = params, load_output = TRUE)
#> Warning in abbreviate_shapefile_names(obj): Field names abbreviated for
#> ESRI Shapefile driver

#> Warning in abbreviate_shapefile_names(obj): Field names abbreviated for
#> ESRI Shapefile driver
#> Warning in py_run_string_impl(code, local, convert): GDAL Message 1: Field
#> HubName of width 255 truncated to 254.
#> $OUTPUT
#> [1] "/tmp/RtmpxFuSHi/nearest.shp"

Created on 2019-03-07 by the reprex package (v0.2.1

Or as I take it from this post the QGIS Plugin NNJoin (I have never used it) provides more or less the same functionality as the GRASS function v.distance. So this would be even another possibility.

havatv commented 4 years ago

The QGIS core algorithm "Join attributes by nearest" should be a good replacement for NNJoin. It is available in QGIS 3.8, and supports "K-nearest neighbour joins".