4

Context

I am trying to download some footway graph from OpenStreetMap (OSM) using osmnx.

Here is a piece of code:

import os, sys
import pandas as pd
import geopandas as gpd
import matplotlib.cm as cm
import matplotlib.colors as colors
import networkx as nx
import osmnx as ox
ox.config(log_console=True, use_cache=True)
ox.__version__

G_test = ox.osm_net_download(polygon=None,
                             north=46.95489, west=7.46006,
                             south=46.95335, east=7.46132,
                             network_type='walk'
                             )

The ox.osm_net_download() method, is based on the Overpass API, so if I check what's in G_test and search for this OSM way 295557051 I can see that the OSM tags are shipped with the data:

{'type': 'way',
    'id': 295557051,
    'nodes': [2992861879,
     2992861880,
     (...) # bunch of vertex coordinates here, skipped for clarity
     2992864399],
    'tags': {'footway': 'sidewalk', 'highway': 'footway', 'surface': 'paved'}
}

The tags are of course the same as the one found by making a direct call to the Overpass API or the OSM API (on which the previous seems to rely) at this address for this way:
https://www.openstreetmap.org/way/295557051

Up to this point, everything is fine.
But the ox.osm_net_download() method doesn't return a networkx graph object, it returns a Python list.

Therefore, to download a graph, I usually query the data through any of the proposed graph_from_*() methods, for example a graph_from_bbox*() as:

G = ox.graph_from_bbox(north=46.95490, west=7.46000,
                       south=46.95330, east=7.46230,
                       network_type='walk',
                       retain_all=True)

Issue

But when downloading the data using the latter method, the OSM tags no longer come with the data!
This is probably due the fact that the graph_from_*() methods are not based on the Overpass API but rather on the Nominatim API.
This may be related to: Cannot get response from nominatim API on some OSM objects

If I explore the result of the G graph, searching for the OSM way 295557051:

G_raw.edges(keys=True, data=True)

One of the may results (as they are many edges composing this OSM feature) look like this:

(2992861879, 2992861880, 0, {'osmid': 295557051, 'highway': 'footway', 'oneway': False, 'length': 4.821}), 

For a better comprehension, we can convert it to a GeoDataFrame using the ox.graph_to_gdfs() method:

G_gdf = ox.graph_to_gdfs(G, 
                         nodes=True, 
                         edges=True, 
                         node_geometry=True, 
                         fill_edge_geometry=True)

And print its content:

G_gdf[1][G_gdf[1]['osmid']==295557051]

GDF from osmnx graph (OSM tags are not there.)

This problem is also propagated when saving the graph to an ESRI Shapefile using ox.save_graph_shapefile():

ox.save_graph_shapefile(G, filename=os.path.join('~/test_graph'))

Indeed, when I open the resulting Shapefile, for example in QGIS, a query on that same way doesn't show the OSM tags in the attribute table.

QGIS screenshot

Question

I wonder where the tags are lost in the process and how to solve for this issue?

Note:

I was first thinking of converting the G graph to a GeoDataFrame, merging it with G_test which I also convert to a GeoDataFrame and then convert back that merged GeoDataFrame to a networkX graph, but I went into a strange error because the retrieved graph doesn't have the right structure:

TypeError: float() argument must be a string or a number, not 'NoneType'

Or to directly write the GeoDataFrame to PostGIS:

AttributeError: 'GeometryDtype' object has no attribute 'base'

But GeoPandas doesn't handle (yet) writing data to PostGIS:
https://github.com/geopandas/geopandas/pull/1248

So I'm stuck.

1
  • 1
    I'm not familiar with osmnx but I doubt that graph_from_*() methods call Nominatim and not Overpass. Nominatim is not suited for obtaining data for a specific bounding box since it is mainly a geocoder. So I guess there must be something else which removes tags after downloading.
    – scai
    Commented Mar 11, 2020 at 11:23

1 Answer 1

5

I had a similar problem, I wanted to access the surface of streets.

Answer

The setting of the attributes that are transferred to the graph are defined in the settings.py

useful_tags_path = ['bridge', 'tunnel', 'oneway', 'lanes', 'ref', 'name',
                    'highway', 'maxspeed', 'service', 'access', 'area',
                    'landuse', 'width', 'est_width', 'junction']

You can edit the settings with ox.utils.config(). I added surface to the list of useful tags. This did the trick.

import osmnx as ox
useful_tags_path = ['bridge', 'tunnel', 'oneway', 'lanes', 'ref', 'name',
                    'highway', 'maxspeed', 'service', 'access', 'area',
                    'landuse', 'width', 'est_width', 'junction', 'surface']
ox.utils.config(useful_tags_path=useful_tags_path)
 (3339714877,
  1395396060,
  {'osmid': 527255117,
   'highway': 'path',
   'surface': 'grass',
   'oneway': False,
   'length': 361.7989999999999,
   'geometry': <shapely.geometry.linestring.LineString at 0x7fe6d9972490>})

I hope this helps you!

EDIT:

You can also manually set the following parameter with a list containing the tags you want:

ox.settings.useful_tags_path = ['surface', 'witdth', 'lanes', ...]

Source: https://osmnx.readthedocs.io/en/stable/osmnx.html#module-osmnx.utils

2
  • Oops, I totally forgot to come back here to post the solution I actually found a few days ago. And indeed, it was the same than the one you posted. But in my case, I have set up the tags I wanted as ox.settings.useful_tags_path = [ list of tags ]. Commented Mar 23, 2020 at 19:00
  • 2
    For anyone else who comes along here, note that the old useful_tags_path setting was deprecated and replaced by the new useful_tags_way setting in a recent release. Same functionality.
    – gboeing
    Commented Jun 12, 2020 at 4:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.