I have a spatVector composed of a single-line geometry that covers the entire road network of my study area. I would like to create a set of N random points over this geometry. I know how to do it in QGIS but I want to do it in R since I have to iterate this process 1'000 times and I want to create a loop.
Do you know any function to do this?
EDIT
First of all, I read my line shapefile using:
Road_network <- vect("path/to/file.shp)
Then I converted it into an SF object:
Road_network_SF <- st_as_sf(Road_network)
And finally, I use both the st_sample
, getting the following results:
Random_points <- st_sample(Road_network_SF, size = 1799)
Random_points
Geometry set for 46350 features (with 44694 geometries empty)
Geometry type: MULTIPOINT
Dimension: XY
Bounding box: xmin: 4503139 ymin: 2504751 xmax: 4622797 ymax: 2613276
Projected CRS: ETRS89-extended / LAEA Europe
First 5 geometries:
MULTIPOINT EMPTY
MULTIPOINT EMPTY
MULTIPOINT EMPTY
MULTIPOINT ((4503139 2574957))
MULTIPOINT EMPTY
and the st_line_sample
function, getting the following error:
Random_points <- st_line_sample(Road_network_SF, n = 1799)
Error in st_line_sample(Road_network_SF, n = 1799) :
inherits(x, "sfc_LINESTRING") non è TRUE
When I converted the spatVector to an sf object, this is what I get:
Road_network_SF
Simple feature collection with 1 feature and 2 fields
Geometry type: MULTILINESTRING
Dimension: XY
Bounding box: xmin: 4500176 ymin: 2504157 xmax: 4626207 ymax: 2616041
Projected CRS: ETRS89-extended / LAEA Europe
FURTHER EDIT The workflow proposed by @Gregory work really good, my error was due to a problem with the road shapefile. I changed it and no further problems occurred, thank you!
Thanks in advance!
CodePudding user response:
You can sample random points along a vector geometry (like roads) with sf::st_sample()
, however the results might seem confusing depending on how you look at them. Here's a reproducible example.
library(sf, quietly = TRUE)
#> Linking to GEOS 3.10.2, GDAL 3.4.2, PROJ 8.2.1; sf_use_s2() is TRUE
library(tigris, quietly = TRUE)
#> To enable
#> caching of data, set `options(tigris_use_cache = TRUE)` in your R script or .Rprofile.
library(ggplot2)
suppressMessages(
roads <- roads(state = "NC",
county = "Mecklenburg")
)
set.seed(1)
rpoints <- st_sample(roads, size = 5)
#> although coordinates are longitude/latitude, st_sample assumes that they are
#> planar
ggplot()
geom_sf(data = roads, color = "grey")
geom_sf(data = rpoints, color = "black")
We see on the map that we have generated 5 random points, as intended. Surprisingly, if you examine the structure of the rpoints
object you'll see that it is a multipoint of length 21672, which you might think is the number of points. However, all but 5 of them have empty geometries. The reason is that there is a geometry (empty for most) for each of the objects that makes up the roads vector.
str(rpoints)
#> sfc_MULTIPOINT of length 21672; first list element: 'XY' num[0 , 1:2] MULTIPOINT EMPTY
head(rpoints)
#> Geometry set for 6 features (with 6 geometries empty)
#> Geometry type: MULTIPOINT
#> Dimension: XY
#> Bounding box: xmin: NA ymin: NA xmax: NA ymax: NA
#> Geodetic CRS: NAD83
#> First 5 geometries:
#> MULTIPOINT EMPTY
#> MULTIPOINT EMPTY
#> MULTIPOINT EMPTY
#> MULTIPOINT EMPTY
#> MULTIPOINT EMPTY
Here's how to get the real points out of there.
rpoints <- rpoints[!st_is_empty(rpoints)]
rpoints
#> Geometry set for 5 features
#> Geometry type: MULTIPOINT
#> Dimension: XY
#> Bounding box: xmin: -81.01691 ymin: 35.07471 xmax: -80.62246 ymax: 35.2948
#> Geodetic CRS: NAD83
#> MULTIPOINT ((-80.88764 35.2948))
#> MULTIPOINT ((-80.62246 35.18395))
#> MULTIPOINT ((-81.01691 35.07471))
#> MULTIPOINT ((-80.78909 35.12663))
#> MULTIPOINT ((-80.83055 35.16959))
Created on 2023-02-01 by the reprex package (v2.0.1)