gboeing / osmnx

OSMnx is a Python package to easily download, model, analyze, and visualize street networks and other geospatial features from OpenStreetMap.
https://osmnx.readthedocs.io
MIT License
4.86k stars 824 forks source link

Add the support for GeoJSON? #622

Closed xingminw closed 3 years ago

xingminw commented 3 years ago

I am wondering whether the authors are interested to add support for the load/save of the street network via GeoJSON. As a human- and machine-readable data format, it is very convenient to use GeoJSON in many cases.

gboeing commented 3 years ago

I had originally gone back and forth about adding GeoJSON graph saving directly into OSMnx's io module. In the end, I left it out as it's relatively simple to do yourself in just a few lines of code:

import osmnx as ox
G = ox.graph_from_place('Piedmont, CA, USA', network_type='drive')

# save graph nodes and edges to disk as GeoJSON
gdf_nodes, gdf_edges = ox.graph_to_gdfs(G)
gdf_nodes = ox.io._stringify_nonnumeric_cols(gdf_nodes)
gdf_edges = ox.io._stringify_nonnumeric_cols(gdf_edges)
gdf_nodes.to_file('nodes.geojson', driver='GeoJSON')
gdf_edges.to_file('edges.geojson', driver='GeoJSON')

Note: the snippet above uses OSMnx's io._stringify_nonnumeric_cols function to convert any non-numeric data to strings: this is important as OSMnx creates some list attributes when simplifying graph topology, but lists don't serialize well. Without that, you'll get an error like ValueError: Invalid field type <class 'list'>

Also, you mentioned:

support for the load/save of the street network via GeoJSON

Note that OSMnx only loads graphs from GraphML files. All the other "saving" functions in the io module are saving only, as we need an explicitly graph file type (like GraphML) to be able to load an existing graph. You can, however, load raw data in a .osm XML file into a graph with the graph_from_xml function. You can also load a GeoPackage or shapefile of nodes/edges as a graph (assuming you have the necessary columns to index by, as shown below) using the graph_from_gdfs function:

import geopandas as gpd
import osmnx as ox

# get graph then save to shapefile with directed=True
G = ox.graph_from_place('Piedmont, CA, USA', network_type='drive')
ox.save_graph_shapefile(G, filepath='./shapefile/', directed=True)

# load shapefiles of nodes and directed edges as a graph
gdf_nodes = gpd.read_file('./shapefile/nodes.shp').set_index('osmid')
gdf_edges = gpd.read_file('./shapefile/edges.shp').set_index(['u', 'v', 'key'])
G2 = ox.graph_from_gdfs(gdf_nodes, gdf_edges)

assert len(G.nodes) == len(G2.nodes)
assert len(G.edges) == len(G2.edges)
xingminw commented 3 years ago

Thanks for your reply and suggestions; it really helps.

I have a follow-up question. As you mentioned,

OSMnx only loads graphs from GraphML files

If I want to manually edit the map (batch delete a group of edges or add some nodes/links), except directly changing the variable through the code, is there any other edit (with visualization) tools to edit the GraphML data? This won't be a question if the OSMnx can load .osm or .geojson file since there are many tools to edit the osm map or geojson map.

The readme file shows that OSMnx can:

Save/load street network to/from a local .osm XML file.

Does your comment mean that OSMnsx cannot load the .osm file?

Thanks!

gboeing commented 3 years ago

If I want to manually edit the map (batch delete a group of edges or add some nodes/links), except directly changing the variable through the code, is there any other edit (with visualization) tools to edit the GraphML data? This won't be a question if the OSMnx can load .osm or .geojson file since there are many tools to edit the osm map or geojson map.

GraphML is an open data format and many network analysis tools are compatible with it. Perhaps the best known is Gephi, which is a GUI tool. Or you can save as shapefile/GeoPackage and re-load with OSMnx as demonstrated in the code snippet above.

Does your comment mean that OSMnx cannot load the .osm file?

It can load .osm files. You can load raw data from a .osm XML file as a graph with the graph_from_xml function.

xingminw commented 3 years ago

Thanks for your patient reply and suggestion. Sorry to bother you. I am not familiar with GIS and map data. I am a transportation guy, just want to find a workflow that suits my application.