Merging route networks

library(stplanr)
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(tmap)
#> The legacy packages maptools, rgdal, and rgeos, underpinning the sp package,
#> which was just loaded, will retire in October 2023.
#> Please refer to R-spatial evolution reports for details, especially
#> https://r-spatial.org/r/2023/05/15/evolution4.html.
#> It may be desirable to make the sf package available;
#> package maintainers should consider adding sf to Suggests:.
#> The sp package is now running under evolution status 2
#>      (status 2 uses the sf package in place of rgdal)
rnet_x = sf::read_sf("https://github.com/ropensci/stplanr/releases/download/v1.0.2/rnet_x_ed.geojson")
rnet_y = sf::read_sf("https://github.com/ropensci/stplanr/releases/download/v1.0.2/rnet_y_ed.geojson")
# dups = duplicated(rnet_x$geometry)
# summary(dups)
# rnet_x = rnet_x |>
#   filter(!dups)
# sf::write_sf(rnet_x, "~/github/ropensci/stplanr/rnet_x_ed.geojson", delete_dsn = TRUE)

Target network preprocessing

We can pre-process the input in a number of ways, e.g.:

tmap_mode("view")
#> tmap mode set to interactive viewing
nrow(rnet_x)
#> [1] 474
summary(sf::st_length(rnet_x))
#> Linking to GEOS 3.11.1, GDAL 3.6.4, PROJ 9.1.1; sf_use_s2() is FALSE
#>     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
#>   0.1018  31.3869  52.9558  73.6990  97.7958 508.7114
plot(sf::st_geometry(rnet_x))

rnet_x = rnet_subset(rnet_x, rnet_y, dist = 20)
#> although coordinates are longitude/latitude, st_union assumes that they are
#> planar
#> although coordinates are longitude/latitude, st_intersection assumes that they
#> are planar
#> Warning: attribute variables are assumed to be spatially constant throughout
#> all geometries
#> Warning in st_cast.sf(sf::st_cast(x, "MULTILINESTRING"), "LINESTRING"):
#> repeating attributes for all sub-geometries for which they may not be constant
#> although coordinates are longitude/latitude, st_intersects assumes that they
#> are planar
nrow(rnet_x)
#> [1] 467
plot(sf::st_geometry(rnet_x))

# rnet_x = rnet_subset(rnet_x, rnet_y, dist = 20, min_x = 5, rm_short = TRUE)
# summary(sf::st_length(rnet_x))
# nrow(rnet_x)
# plot(sf::st_geometry(rnet_x))
rnet_x = rnet_subset(rnet_x, rnet_y, dist = 20, rm_disconnected = TRUE)
#> although coordinates are longitude/latitude, st_union assumes that they are
#> planar
#> although coordinates are longitude/latitude, st_intersection assumes that they
#> are planar
#> Warning: attribute variables are assumed to be spatially constant throughout
#> all geometries

#> Warning: repeating attributes for all sub-geometries for which they may not be
#> constant
#> although coordinates are longitude/latitude, st_intersects assumes that they
#> are planar
nrow(rnet_x)
#> [1] 468
plot(sf::st_geometry(rnet_x))

funs = list(value = sum, Quietness = mean)
brks = c(0, 100, 500, 1000, 5000)
rnet_merged = rnet_merge(rnet_x, rnet_y, dist = 20, segment_length = 20, funs = funs)
#> although coordinates are longitude/latitude, st_union assumes that they are
#> planar
#> although coordinates are longitude/latitude, st_intersection assumes that they
#> are planar
#> Warning: attribute variables are assumed to be spatially constant throughout
#> all geometries
#> Warning in st_cast.sf(sf::st_cast(x, "MULTILINESTRING"), "LINESTRING"):
#> repeating attributes for all sub-geometries for which they may not be constant
#> although coordinates are longitude/latitude, st_intersects assumes that they
#> are planar
#> Warning: st_centroid assumes attributes are constant over geometries
#> Warning in st_centroid.sfc(st_geometry(x), of_largest_polygon =
#> of_largest_polygon): st_centroid does not give correct centroids for
#> longitude/latitude data
#> although coordinates are longitude/latitude, st_intersects assumes that they
#> are planar
#> Joining with `by = join_by(identifier)`
m1 = tm_shape(rnet_y) + tm_lines("value", palette = "viridis", lwd = 5, breaks = brks)  +
  tm_scale_bar()
m2 = tm_shape(rnet_merged) + tm_lines("value", palette = "viridis", lwd = 5, breaks = brks)
tmap_arrange(m1, m2, sync = TRUE)
#> Warning: Values have found that are higher than the highest break
#> Warning: Values have found that are higher than the highest break

We can more reduce the minimum segment length to ensure fewer NA values in the outputs:

rnet_merged = rnet_merge(rnet_x, rnet_y, dist = 20, segment_length = 10, funs = funs)
#> although coordinates are longitude/latitude, st_union assumes that they are
#> planar
#> although coordinates are longitude/latitude, st_intersection assumes that they
#> are planar
#> Warning: attribute variables are assumed to be spatially constant throughout
#> all geometries
#> Warning in st_cast.sf(sf::st_cast(x, "MULTILINESTRING"), "LINESTRING"):
#> repeating attributes for all sub-geometries for which they may not be constant
#> although coordinates are longitude/latitude, st_intersects assumes that they
#> are planar
#> Warning: st_centroid assumes attributes are constant over geometries
#> Warning in st_centroid.sfc(st_geometry(x), of_largest_polygon =
#> of_largest_polygon): st_centroid does not give correct centroids for
#> longitude/latitude data
#> although coordinates are longitude/latitude, st_intersects assumes that they
#> are planar
#> Joining with `by = join_by(identifier)`
m1 = tm_shape(rnet_y) + tm_lines("value", palette = "viridis", lwd = 5, breaks = brks)
m2 = tm_shape(rnet_merged) + tm_lines("value", palette = "viridis", lwd = 5, breaks = brks)
tmap_arrange(m1, m2)
#> Warning: Values have found that are higher than the highest break
#> Warning: Values have found that are higher than the highest break
rnet_merged = rnet_merge(rnet_x, rnet_y, dist = 20, segment_length = 10, funs = funs, dist_subset = 30)
#> although coordinates are longitude/latitude, st_union assumes that they are
#> planar
#> although coordinates are longitude/latitude, st_intersection assumes that they
#> are planar
#> Warning: attribute variables are assumed to be spatially constant throughout
#> all geometries
#> Warning in st_cast.sf(sf::st_cast(x, "MULTILINESTRING"), "LINESTRING"):
#> repeating attributes for all sub-geometries for which they may not be constant
#> although coordinates are longitude/latitude, st_intersects assumes that they
#> are planar
#> Warning: st_centroid assumes attributes are constant over geometries
#> Warning in st_centroid.sfc(st_geometry(x), of_largest_polygon =
#> of_largest_polygon): st_centroid does not give correct centroids for
#> longitude/latitude data
#> although coordinates are longitude/latitude, st_intersects assumes that they
#> are planar
#> Joining with `by = join_by(identifier)`
m1 = tm_shape(rnet_y) + tm_lines("value", palette = "viridis", lwd = 5, breaks = brks)
m2 = tm_shape(rnet_merged) + tm_lines("value", palette = "viridis", lwd = 5, breaks = brks)
tmap_arrange(m1, m2, sync = TRUE)
#> Warning: Values have found that are higher than the highest break
#> Warning: Values have found that are higher than the highest break
sum(rnet_merged$value * sf::st_length(rnet_merged), na.rm = TRUE)
#> 24460963 [m]
sum(rnet_y$value * sf::st_length(rnet_y), na.rm = TRUE)
#> 17164314 [m]