Open luukvdmeer opened 4 years ago
regarding minimum spanning tree this can be accomplished using spdep and sfdep. here's an example of creating an sfnetwork using an mstree.
library(sf)
library(dplyr)
library(sfdep)
library(sfnetworks)
geo <- sfdep::guerry_nb |>
select(geometry) |>
mutate(nb = st_complete_nb(n()),
wt = st_nb_dists(geometry, nb))
#> ! Polygon provided. Using point on surface.
listw <- recreate_listw(geo$nb, structure(geo$wt, "B" = TRUE))
ms <- spdep::mstree(listw)
ms_df <- as.data.frame(ms) |>
rlang::set_names(c("from", "to", "edge_length"))
geom <- sf::st_centroid(geo)[["geometry"]]
#> Warning in st_centroid.sf(geo): st_centroid assumes attributes are constant over
#> geometries of x
nodes <- geom
from <- geom[ms_df$from]
to <- geom[ms_df$to]
from <- as_tibble(st_coordinates(from)) |>
mutate(id = row_number())
to <- as_tibble(st_coordinates(to)) |>
mutate(id = row_number())
# need to find a way to arrange using base R
edges2 <- sfheaders::sf_linestring(
arrange(bind_rows(from, to), id),
x = "X",
y = "Y",
linestring_id = "id") |>
bind_cols(ms_df)
plot(sfnetwork(nodes, edges2))
#> Checking if spatial network structure is valid...
#> Spatial network structure is valid
Created on 2022-08-23 by the reprex package (v2.0.1)
Creating an sfnetwork using spdep + sfdep for delaunay triangulation and gabriel neighbors
# spdep -------------------------------------------------------------------
library(sf)
#> Linking to GEOS 3.9.1, GDAL 3.2.3, PROJ 7.2.1; sf_use_s2() is TRUE
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
library(spdep)
#> Loading required package: sp
#> Loading required package: spData
#> To access larger datasets in this package, install the spDataLarge
#> package with: `install.packages('spDataLarge',
#> repos='https://nowosad.github.io/drat/', type='source')`
library(sfnetworks)
nodes <- st_centroid(sfdep::guerry)
#> Warning in st_centroid.sf(sfdep::guerry): st_centroid assumes attributes are
#> constant over geometries of x
geo <- st_geometry(nodes)
nb <- tri2nb(geo)
plot(nb, geo)
wt <- sfdep::st_nb_dists(geo, nb)
sfdep::st_as_graph(geo, nb, wt) |>
plot()
#> Checking if spatial network structure is valid...
#> Spatial network structure is valid
# gabriel neighbors
# ensure that it is symmetric to make sure no missing links
nb <- graph2nb(gabrielneigh(geo), sym = TRUE)
wt <- sfdep::st_nb_dists(geo, nb)
sfdep::st_as_graph(geo, nb, wt) |>
plot()
#> Checking if spatial network structure is valid...
#> Spatial network structure is valid
Created on 2022-08-23 by the reprex package (v2.0.1)
Is your feature request related to a problem? Please describe. You can now create an
sfnetwork
from only a set of spatial linestrings. The linestrings will be the edges, and the endpoints of the linestrings the nodes. Also, you can create ansfnetwork
from only a set of spatial points. The points will be the nodes, and edges will be created in a sequential order (i.e. from node 1 to 2, node 2 to 3, etc). This was created as a solution for this StackOverflow issue.However, there are much more ways to create a spatial graph from only a set of points. Dale (2017) lists the most common ones:
Describe the solution you'd like More options to create an
sfnetwork
from only a set of spatial points. This could be implemented with an extra argument toas_sfnetwork.sf
, specifying which creation algorithm to use, and also in the same style as tidygraphscreate_*
family of functions. That is:create_mnn
,create_nn
,create_mst
, et cetera.