2

I am trying to build a road network by using sfnetworks package in R, and I ran into an issue while running the last code chunk.

The below is my R code and data available here:

# Read in Data

## London borough boundary
LondonBoroughs <- st_read(here::here('data', 'boundary', 'London_Borough_Excluding_MHW.shp')) %>%
  st_transform(., 27700)

## street nodes
street_nodes <- st_read(here::here('data', 'cleaned_nodes.geojson')) %>% st_transform(., 27700)


## street edges
street_edges <- st_read(here::here('data', 'cleaned_edges.geojson')) %>% st_transform(., 27700)

The street_nodes variable has 6 columns and osmid(int64) as row index: y(float64), x(float64), highway(object), ref(object), geometry(geometry).

The street_edges variable has 12 columns: u(int64), v(int64), key(int64), osmid(object), oneway(boolean), length(float64), from(int64), to(int64), junction(object), area(object), landuse(object), geometry(geomtery)

# Data cleaning

## remove duplicate street nodes - no duplicates
street_nodes <- street_nodes %>%
  distinct()

## street nodes within London boundary
street_nodes <- street_nodes[LondonBoroughs, ]

## street edges within London boundary
street_edges <- street_edges[LondonBoroughs, ]

## remove duplicate street edges - no duplicates
street_edges <- street_edges %>%
  distinct()
# create network
net = sfnetwork(street_nodes, street_edges, directed = FALSE)

When I run the last code chunk, it throws the following error message:

Error in (function (edges, n = max(edges), directed = TRUE) : At core/graph/type_indexededgelist.c:117 : Number of vertices must not be negative. Invalid value

The below are what I did in Python:

I queried the OSM road networks in Python and did a bit of data preprocessing, such as converting datatype and filling na values. The initially preprocessed edge and node data were saved in geojson format.

import os
import wget
import osmnx as ox
import geopandas as gpd

# bounding box of London
bbox = (-0.5108706, 51.28117, 0.322123, 51.68948)

# get road network and save as .shp
G = ox.graph_from_bbox(bbox[3], bbox[1], bbox[2], bbox[0], network_type='all')

ox.save_graph_shapefile(G, filepath='data/london_street/raw_osm_data', encoding='utf-8')

# load as GeoDataFrame
nodes = gpd.read_file('data/london_street/raw_osm_data/nodes.shp')
edges = gpd.read_file('data/london_street/raw_osm_data/edges.shp')

# node column rename
nodes.rename(columns = {'street_cou' : 'street_count'}, inplace = True)

# replace 'None' to empty string in node data
nodes.fillna("",inplace=True)

cleaned_nodes = nodes.copy()
cleaned_nodes.set_index('osmid', inplace = True)
cleaned_nodes.head(3)


# replace 'None' to empty string in edge data
edges.fillna("",inplace=True)

# select columns of interest
cleaned_edges = edges[['u', 'v', 'key', 'osmid', 'oneway', 'length', 'from', 'to', 'junction',
       'area', 'landuse', 'geometry']].copy()
cleaned_edges.head(1)

# convert 'oneway' datatype to boolean
cleaned_edges['oneway'] = cleaned_edges['oneway'].astype(bool)

# save the cleaned nodes and edges
file_path_nodes = "data/london_street/cleaned_osm_data/cleaned_nodes.geojson"
cleaned_nodes.to_file(file_path_nodes, driver = "GeoJSON")

file_path_edges = "data/london_street/cleaned_osm_data/cleaned_edges.geojson"
cleaned_edges.to_file(file_path_edges, driver = "GeoJSON")

In case, the function assumes that there should be nodes for every integer between min(street_nodes$osmid) (2) and max(street_nodes$osmid) I experimented to change the datatypes of "to" and "from" columns in edge data and 'osmid' column in node data to a 'character' type. But nothing worked and still got the same error message.

Could anyone help?

Phil
  • 37
  • 5
  • Welcome to Stack Overflow. The problem seems to be either with your original file, or one of your preprocessing steps, which makes it difficult to provide specific advice. Two questions: 1. Have you checked/fixed the validity of your geometry with [`st_make_valid()`](https://r-spatial.github.io/sf/reference/valid.html). 2. What is your overall goal after building the road network? I've done a lot of work with London roads from R using osrm and haven't run into these kinds of problems. Might be worth considering, depending what you're trying to do. – SamR Jun 20 '23 at 19:41
  • Thank you for your comment, Sam. Regarding your questions, 1) I checked the validity of geometry and both data seem fine. The node is in point and the edge is in linestring geometry. 2) Once I build the network, I am planning on projecting POIs to the network, and calculating the travel distance/time to the POIs. I googled if anyone ran into this issue, but I did not find anyone who experienced the same problem as I did... – Phil Jun 20 '23 at 20:04
  • The shapefile I read in R is London Boundary data from London Data Store! I wanted to clip street_edges and street_nodes to the London boundary so I also read in the boundary data to do spatial subsetting:) – Phil Jun 20 '23 at 20:10
  • I don't see an obvious problem, but your workflow seems a little odd. For an alternative approach to calculating road distances to specific points in R using osrm see [here](https://stackoverflow.com/questions/75791459/r-calculating-the-distance-between-two-geographical-points/). For converting a shapefile to an `sfnetwork` object directly in R, without preprocessing in Python or splitting nodes and edges see [here](https://stackoverflow.com/questions/75923204/calculating-distances-between-points-on-a-shapefile/76102963#76102963). – SamR Jun 20 '23 at 20:17
  • 1
    Thank you very much for your help! I will have a read at the posts:) – Phil Jun 20 '23 at 20:21
  • Do you face the same problem with other bounding boxes? And could you replicate the error using smaller datasets? If so, could you share them? – agila Jun 21 '23 at 16:08

0 Answers0