Home > Enterprise >  Create random points over a line spatvector in R
Create random points over a line spatvector in R

Time:02-02

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)

  • Related