Open luukvdmeer opened 4 years ago
There is now a method for sfNetwork
from stplanr
(in develop):
library(sfnetworks)
library(stplanr)
sln = SpatialLinesNetwork(roxel)
sfn = as_sfnetwork(sln)
It might not be as efficient as possible yet. It simply recreates the network with the @sl
slot, and in addition takes the directedness from the @g
slot.
Regarding dodgr
: the dodgr network object are of class c("data.frame", "dodgr_streetnet")
. So providing it to as_sfnetwork
will try the data.frame
method, which actually runs without errors because tidygraph
supports data frames as input, but the result is not correct of course (it treats the first two columns as from
and to
). Instead, a function dodgr_to_sfnetwork
could be used:
dodgr_to_sfnetwork = function(graph) {
requireNamespace("dodgr")
as_sfnetwork(
dodgr::dodgr_to_tidygraph(graph),
force = TRUE,
coords = c("x", "y"),
crs = 4326
)
}
Then:
library(dodgr)
graph = weight_streetnet(hampi)
graph
#> geom_num edge_id from_id from_lon from_lat to_id to_lon
#> 1 1 1 339318500 76.47489 15.34169 339318502 76.47612
#> 2 1 2 339318502 76.47612 15.34173 339318500 76.47489
#> 3 1 3 339318502 76.47612 15.34173 2398958028 76.47621
#> 4 1 4 2398958028 76.47621 15.34174 339318502 76.47612
#> 5 1 5 2398958028 76.47621 15.34174 1427116077 76.47628
#> 6 1 6 1427116077 76.47628 15.34179 2398958028 76.47621
#> to_lat d d_weighted highway way_id component
#> 1 15.34173 132.442169 147.15797 unclassified 28565950 1
#> 2 15.34169 132.442169 147.15797 unclassified 28565950 1
#> 3 15.34174 8.888670 9.87630 unclassified 28565950 1
#> 4 15.34173 8.888670 9.87630 unclassified 28565950 1
#> 5 15.34179 9.326536 10.36282 unclassified 28565950 1
#> 6 15.34174 9.326536 10.36282 unclassified 28565950 1
#> time time_weighted
#> 1 31.786121 35.317912
#> 2 31.786121 35.317912
#> 3 2.133281 2.370312
#> 4 2.133281 2.370312
#> 5 2.238369 2.487076
#> 6 2.238369 2.487076
dodgr_to_sfnetwork(graph)
#> # An sfnetwork with 2926 nodes and 5973 edges
#> #
#> # CRS: EPSG:4326
#> #
#> # A directed simple graph with 3 components and spatially implicit edges
#> #
#> # Node Data: 2,926 x 4 (active)
#> # Geometry type: POINT
#> # Dimension: XY
#> # Bounding box: xmin: 76.37263 ymin: 15.30107 xmax: 76.60668 ymax:
#> # 15.40121
#> name component n geometry
#> <chr> <int> <dbl> <POINT [°]>
#> 1 339318500 1 0 (76.47489 15.34169)
#> 2 339318502 1 1 (76.47612 15.34173)
#> 3 2398958028 1 2 (76.47621 15.34174)
#> 4 1427116077 1 3 (76.47628 15.34179)
#> 5 339318503 1 4 (76.47641 15.3419)
#> 6 2398958034 1 5 (76.4765 15.34199)
#> # … with 2,920 more rows
#> #
#> # Edge Data: 5,973 x 11
#> from to weight d_weighted time time_weighted xfr yfr xto
#> <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 2 132. 147. 31.8 35.3 76.5 15.3 76.5
#> 2 2 1 132. 147. 31.8 35.3 76.5 15.3 76.5
#> 3 2 3 8.89 9.88 2.13 2.37 76.5 15.3 76.5
#> # … with 5,970 more rows, and 2 more variables: yto <dbl>,
#> # component <int>
In dodgr
there are more of such conversion functions, like dodgr_to_igraph
, dodgr_to_tidygraph
etc. I think dodgr_to_sfnetwork
would therefore fit better as part of dodgr (when we have a more stable version of the package of course).
Regarding linnet
:
At the moment it's possible to convert a linnet object to an sf object and then apply the usual methods.
@agila do you remember which function?
Hi! This is an example of converting a linnet
object into sf
format:
# packages
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1
library(spatstat)
#> Loading required package: spatstat.data
#> Loading required package: nlme
#> Loading required package: rpart
#>
#> spatstat 1.64-1 (nickname: 'Help you I can, yes!')
#> For an introduction to spatstat, type 'beginner'
# data
class(simplenet)
#> [1] "linnet" "list"
plot(simplenet, main = "Linnet")
# transform into sf format
simplenet_sf <- st_as_sf(as.psp(simplenet))
simplenet_sf
#> Simple feature collection with 11 features and 1 field
#> geometry type: GEOMETRY
#> dimension: XY
#> bbox: xmin: 0 ymin: 0 xmax: 1 ymax: 1
#> CRS: NA
#> First 10 features:
#> label geom
#> 1 window POLYGON ((0 0, 1 0, 1 1, 0 ...
#> 2 segment LINESTRING (0.181276 0.8345...
#> 3 segment LINESTRING (0.1497036 0.211...
#> 4 segment LINESTRING (0.3254689 0.460...
#> 5 segment LINESTRING (0.4411403 0.160...
#> 6 segment LINESTRING (0.3254689 0.460...
#> 7 segment LINESTRING (0.5358572 0.802...
#> 8 segment LINESTRING (0.5358572 0.802...
#> 9 segment LINESTRING (0.3795058 0.320...
#> 10 segment LINESTRING (0.8418658 0.277...
plot(st_geometry(st_collection_extract(simplenet_sf, "LINESTRING")), main = "sf")
Created on 2020-06-07 by the reprex package (v0.3.0)
There are a few caveats:
POLYGON
geometry is the window
of the linnet
(like a polygonal bbox). sf
methods for psp
objects were created in sf
0.8.1. linnet
object into sf
format without passing through psp
format but I don't think it's a big deal now. We can add that as "future work". Great to see this development work happening, awesome that we can now convert, will make testing/comparing/switching between implementations easier.
I think we have implemented the most important methods, so I will move this issue to milestone 3 for the remaining ones.
Additionally, we should do a PR to dodgr
for a dodgr_to_sfnetwork
function.
Self note: Prof. Baddeley started working on a separate project for linnet class (https://github.com/baddstats/spatstat.linnet) so check if we need to update the dependencies and other methods for conversions.
Method for sfc
objects is now added on develop
Hi! One question since I don't know what are the "best practices" in these cases. I would like adding a new method to convert sfnetwork
objects into linnet objects (since, AFAIK, that's the main R package for statistical analysis of point patterns on networks). Should I add a new PR here or in the spatstat
repo?
I am not sure what the best practice is, maybe @Robinlovelace has an idea? It maybe depends also on how open the spatstat
developers are to such pull requests. We can implement it in sfnetworks
since as_tbl_graph
, st_as_sf
and as_tibble
fall in the same category and are all implemented in sfnetworks
.
My first impression is that adding the functionality to sfnetworks
makes sense, unless there are function in linnet
that are needed in which case it would make sense to put in a PR there. No harm in asking a question on their issue tracker before opening a PR - that's probably best practice: ask before doing can save lots of time in my experience.
Other packages to look into regarding integration with sfnetworks: spdep
and spatgraph
Another package that I want to check sooner or later is MetricGraph
. They implement a new class called metric_graph
for spatial analysis on linear networks.
Is your feature request related to a problem? Please describe. Right now, you can already convert a lot of graph objects to an sfnetwork object, if 1) they are a
tbl_graph
or can be converted to atbl_graph
withas_tbl_graph
AND 2) at least the nodes can be converted to ansf
object withst_as_sf
. Theas_tbl_graph
function supports a large amount of graph data structures in R.However, in
sfnetwork
we also want to support the most important spatial network data structures that already exist.Describe the solution you'd like More methods for
as_sfnetwork
, addressing the most important spatial network data structures in R.An overview (this list will be updated):
tbl_graph
fromtidygraph
sf
fromsf
sfc
fromsf
dodgr_streetnet
fromdodgr
SpatialLinesNetwork
fromstplanr
linnet
fromspatstat
(https://rdrr.io/cran/spatstat/man/linnet.html).mgNetwork
fromrmangal
SpatialNetwork
fromspnetwork
@Robinlovelace @agila5 @loreabad6 and others, please feel free to add more classes in the comments!