sfnetwork
is a tidy data structure for geospatial networks. It
extends the tbl_graph
data structure for
relational data into the domain of geospatial networks, with nodes and
edges embedded in geographical space, and offers smooth integration with
sf
for spatial data analysis.
sfnetwork(
nodes,
edges = NULL,
directed = TRUE,
node_key = "name",
edges_as_lines = NULL,
length_as_weight = FALSE,
force = FALSE,
message = TRUE,
...
)
The nodes of the network. Should be an object of class
sf
, or directly convertible to it using
st_as_sf
. All features should have an associated geometry
of type POINT
.
The edges of the network. May be an object of class
sf
, with all features having an associated geometry of
type LINESTRING
. It may also be a regular data.frame
or
tbl_df
object. In any case, the nodes at the ends of
each edge must either be encoded in a to
and from
column, as
integers or characters. Integers should refer to the position of a node in
the nodes table, while characters should refer to the name of a node encoded
in the column referred to in the node_key
argument. Setting edges to
NULL
will create a network without edges.
Should the constructed network be directed? Defaults to
TRUE
.
The name of the column in the nodes table that character
represented to
and from
columns should be matched against. If
NA
, the first column is always chosen. This setting has no effect if
to
and from
are given as integers. Defaults to 'name'
.
Should the edges be spatially explicit, i.e. have
LINESTRING
geometries stored in a geometry list column? If
NULL
, this will be automatically defined, by setting the argument to
TRUE
when the edges are given as an object of class
sf
, and FALSE
otherwise. Defaults to NULL
.
Should the length of the edges be stored in a column
named weight
? If set to TRUE
, this will calculate the length
of the linestring geometry of the edge in the case of spatially explicit
edges, and the straight-line distance between the source and target node in
the case of spatially implicit edges. If there is already a column named
weight
, it will be overwritten. Defaults to FALSE
.
Should network validity checks be skipped? Defaults to
FALSE
, meaning that network validity checks are executed when
constructing the network. These checks guarantee a valid spatial network
structure. For the nodes, this means that they all should have POINT
geometries. In the case of spatially explicit edges, it is also checked that
all edges have LINESTRING
geometries, nodes and edges have the same
CRS and boundary points of edges match their corresponding node coordinates.
These checks are important, but also time consuming. If you are already sure
your input data meet the requirements, the checks are unnecessary and can be
turned off to improve performance.
Should informational messages (those messages that are
neither warnings nor errors) be printed when constructing the network?
Defaults to TRUE
.
Arguments passed on to st_as_sf
, if nodes need
to be converted into an sf
object during construction.
An object of class sfnetwork
.
library(sf, quietly = TRUE)
## Create sfnetwork from sf objects
p1 = st_point(c(7, 51))
p2 = st_point(c(7, 52))
p3 = st_point(c(8, 52))
nodes = st_as_sf(st_sfc(p1, p2, p3, crs = 4326))
e1 = st_cast(st_union(p1, p2), "LINESTRING")
e2 = st_cast(st_union(p1, p3), "LINESTRING")
e3 = st_cast(st_union(p3, p2), "LINESTRING")
edges = st_as_sf(st_sfc(e1, e2, e3, crs = 4326))
edges$from = c(1, 1, 3)
edges$to = c(2, 3, 2)
# Default.
sfnetwork(nodes, edges)
#> Checking if spatial network structure is valid...
#> Spatial network structure is valid
#> # A sfnetwork with 3 nodes and 3 edges
#> #
#> # CRS: EPSG:4326
#> #
#> # A directed acyclic simple graph with 1 component with spatially explicit edges
#> #
#> # A tibble: 3 × 1
#> x
#> <POINT [°]>
#> 1 (7 51)
#> 2 (7 52)
#> 3 (8 52)
#> #
#> # A tibble: 3 × 3
#> from to x
#> <int> <int> <LINESTRING [°]>
#> 1 1 2 (7 51, 7 52)
#> 2 1 3 (7 51, 8 52)
#> 3 3 2 (8 52, 7 52)
# Undirected network.
sfnetwork(nodes, edges, directed = FALSE)
#> Checking if spatial network structure is valid...
#> Spatial network structure is valid
#> # A sfnetwork with 3 nodes and 3 edges
#> #
#> # CRS: EPSG:4326
#> #
#> # An undirected simple graph with 1 component with spatially explicit edges
#> #
#> # A tibble: 3 × 1
#> x
#> <POINT [°]>
#> 1 (7 51)
#> 2 (7 52)
#> 3 (8 52)
#> #
#> # A tibble: 3 × 3
#> from to x
#> <int> <int> <LINESTRING [°]>
#> 1 1 2 (7 51, 7 52)
#> 2 1 3 (7 51, 8 52)
#> 3 2 3 (8 52, 7 52)
# Using character encoded from and to columns.
nodes$name = c("city", "village", "farm")
edges$from = c("city", "city", "farm")
edges$to = c("village", "farm", "village")
sfnetwork(nodes, edges, node_key = "name")
#> Checking if spatial network structure is valid...
#> Spatial network structure is valid
#> # A sfnetwork with 3 nodes and 3 edges
#> #
#> # CRS: EPSG:4326
#> #
#> # A directed acyclic simple graph with 1 component with spatially explicit edges
#> #
#> # A tibble: 3 × 2
#> x name
#> <POINT [°]> <chr>
#> 1 (7 51) city
#> 2 (7 52) village
#> 3 (8 52) farm
#> #
#> # A tibble: 3 × 3
#> from to x
#> <int> <int> <LINESTRING [°]>
#> 1 1 2 (7 51, 7 52)
#> 2 1 3 (7 51, 8 52)
#> 3 3 2 (8 52, 7 52)
# Spatially implicit edges.
sfnetwork(nodes, edges, edges_as_lines = FALSE)
#> Checking if spatial network structure is valid...
#> Spatial network structure is valid
#> # A sfnetwork with 3 nodes and 3 edges
#> #
#> # CRS: EPSG:4326
#> #
#> # A directed acyclic simple graph with 1 component with spatially implicit edges
#> #
#> # A tibble: 3 × 2
#> x name
#> <POINT [°]> <chr>
#> 1 (7 51) city
#> 2 (7 52) village
#> 3 (8 52) farm
#> #
#> # A tibble: 3 × 2
#> from to
#> <int> <int>
#> 1 1 2
#> 2 1 3
#> 3 3 2
# Store edge lenghts in a weight column.
sfnetwork(nodes, edges, length_as_weight = TRUE)
#> Checking if spatial network structure is valid...
#> Spatial network structure is valid
#> # A sfnetwork with 3 nodes and 3 edges
#> #
#> # CRS: EPSG:4326
#> #
#> # A directed acyclic simple graph with 1 component with spatially explicit edges
#> #
#> # A tibble: 3 × 2
#> x name
#> <POINT [°]> <chr>
#> 1 (7 51) city
#> 2 (7 52) village
#> 3 (8 52) farm
#> #
#> # A tibble: 3 × 4
#> from to x weight
#> <int> <int> <LINESTRING [°]> [m]
#> 1 1 2 (7 51, 7 52) 111195.
#> 2 1 3 (7 51, 8 52) 130977.
#> 3 3 2 (8 52, 7 52) 68458.
# Adjust the number of features printed by active and inactive components
oldoptions = options(sfn_max_print_active = 1, sfn_max_print_inactive = 2)
sfnetwork(nodes, edges)
#> Checking if spatial network structure is valid...
#> Spatial network structure is valid
#> # A sfnetwork with 3 nodes and 3 edges
#> #
#> # CRS: EPSG:4326
#> #
#> # A directed acyclic simple graph with 1 component with spatially explicit edges
#> #
#> # A tibble: 3 × 2
#> x name
#> <POINT [°]> <chr>
#> 1 (7 51) city
#> # ℹ 2 more rows
#> #
#> # A tibble: 3 × 3
#> from to x
#> <int> <int> <LINESTRING [°]>
#> 1 1 2 (7 51, 7 52)
#> 2 1 3 (7 51, 8 52)
#> # ℹ 1 more row
options(oldoptions)