I have a set of forest stands (SpatialPolygonDataFrame) distributed randomly over the landscape, i.e. dispersed and aggregated. For each polygon, I want to decide if it has an open edge or not. Polygon has open edge if:
- has no neighbors
- has no neighbors at least on one side;
- has neighbors, but the difference between the tree height between stand and neighbors is more than 5
I wander how to add attribute open_edge = TRUE/FALSE
to individual polygons? In raster
package, there is a promising approach using moving window
. However, my original data are feature classes, and unfortunately are not so raster like as in the working example.
I though to (pseudocode):
- subset each stand one by one (in
for
loop) - create surrounding buffer
- subset surrounding stand by overlap of
buffer
with the stands - if any neighbors -> compare the height. If difference > 5,
open_edge = TRUE
But, this approach does not consider what the stand has let's say neighbors only at 3 sides, i.e. as rook neighborhood. The poly2nb
tool seems promising, but how to add attributes to individual stands?
Here is my dummy approach but I wonder if you have a more efficient solution?
Create dummy data:
library(ggplot2) # for choropleth map plot
library(broom) # to convert spatial data to dataframe
library(mapproj)
library(spdep) # neighbours
library(rgdal)
library(rgeos)
library(sf)
library(raster)
library(dplyr)
library(spData)
library(sf)
r <- raster(nrow=6, ncol=6, crs = "+init=epsg:2957")
values(r) <- matrix(data = c(9, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA,
NA, NA, NA, 1, 1, 1,
NA, NA, NA, 1, 9, 1,
NA, NA, NA, 1, 1, 1),
nrow = 6,
ncol = 6,
byrow = TRUE)
# Convert raster to polygon
polys <- rasterToPolygons(r)
Identify if stand has open edge, on example of one stand:
# Subset first row in SpatialPolygonDataFrame
i = 10
one = polys[i, ]
# Keep the remaining polygons
left = polys[-i,]
# Create buffer within distance
buff = buffer(one, width = 100)
# subset set of neighbours by spatial overlap
nbrs <- left[which(gContains(sp::geometry(buff),
sp::geometry(left), byid = T)),
# Compare if the values are different
height.one = rep(one$layer[1], nrow(nbrs))
height.nbrs = nbrs$layer
# Get the differences between the neighbouring stands
difference = height.one - height.nbrs
# If the difference in at least one stand is
# in more than 5, set open_edge = TRUE
# or if no neighbours find
one$open_edge <- any(difference > 5)