[GIS] How to create random point in according polygon for each dataset entry in a list (with R)

point-in-polygonqgisrrandom

I have an area divided into polygons, and a dataset of observations which has a common field with the polygon layer.

I now would like to generate a random point for each dataset entry within the according polygon.

R was already a great help in digesting the dataset and even to produce shapefiles with summed values of the dataset, so I dare to post this here in the gis.stackexchange.
It would be nice to have a solution in R, cause i have to create multiple subsets which can so easily be done there by a loop, so i do no have to filter the data manually in QGIS all the time.

Other solution are welcome as well.
enter image description here

Polygonlayer: 39 Polygons

Polyid
A1
O19
A13

Datalist: 1360 Data entries

Polyid, value1, value2, value3
A17, ..., ..., ...
O6, ..., ...
A3, ...
A4, ...
O6, ...
A8, ...
A17, ...

Goal: -> Having a point-shape with 1360 random points, which reside in the according polygon and have all attributes of the datalist.

Best Answer

You can use spsample for this. You need to set the "iter" argument depending on how your polygons are shaped, but this code generates a coordinate from each polygon in the wrld_simpl data set. Using iter=10 found a coordinate for each polygon for these data (but 4 failed a few times).

library(sp);library(maptools)
data(wrld_simpl)
s <- matrix(as.numeric(NA), nrow(wrld_simpl), 2)
for (i in seq_len(nrow(s))) s[i,] <- as.vector(coordinates(spsample(wrld_simpl[i,], type = "random", n = 1, iter = 10)))

Balancing the right ways of sampling in order to ensure always an intersecting point is always found may take some care, see the help page details for ?spsample. Note this is sampling in longlat so it's not exactly sensible, but that will depend on your data, not the function.

This is treating each row in the SpatialPolygonsDataFrame as an entity to sample from, so only one point per "multipolygon". There are methods for Polygon, Polygons and SpatialPolygons so it will work similarly for those with slightly different code depending on what you have.

Note that coordinates(x) will give you centroid of each polygon, but that's obviously not guaranteed to land in the shape itself. Also, spsample assumes that any holes are sensibly defined.

With that matrix each row is a one-to-one match to rows in the polygon layer, so

res <- SpatialPointsDataFrame(s, as.data.frame(wrld_simpl), proj4string = CRS(proj4string(wrld_simpl)))

finishes the job, but it depends on what your objects are and how you deal with them. Record matching and transfer is pretty basic in R, but not exactly on-topic here.