使用graph_from_gdfs重建图后调用OSMnx simplify_graph抛TypeError
问题:如何避免Osmnx简化图时的TypeError并成功简化重建后的图?
问题背景
工作流如下:ox.graph_from_polygon => graph_to_gdfs => 修改gdf_edges => ox.graph_from_gdfs => ox.simplify_graph
执行到ox.simplify_graph时抛出TypeError: unhashable type: 'list',错误位置在Osmnx的simplification.py第362行:
File .../osmnx/simplification.py:362, in simplify_graph(G, strict, edge_attrs_differ, endpoint_attrs, remove_rings, track_merged) 359 if attr in attrs_to_sum: 360 # if this attribute must be summed, sum it now 361 path_attributes[attr] = sum(path_attributes[attr]) --> 362 elif len(set(path_attributes[attr])) == 1: 363 # if there's only 1 unique value in this attribute list,
即使未修改数据框也会触发该错误,最小复现示例:
import shapely import osmnx as ox poly = shapely.from_wkt("POLYGON((9.493474960327147 51.228210969202365," "9.493346214294432 51.223359875812804," "9.498442411422728 51.22356145497176," "9.498571157455443 51.228036284963565," "9.493474960327147 51.228210969202365))") G = ox.graph_from_polygon(poly, network_type="drive") nodes_gdf, edges_gdf = ox.graph_to_gdfs(G.to_undirected()) G2 = ox.graph_from_gdfs(gdf_nodes=nodes_gdf, gdf_edges=edges_gdf) nodes_gdf_2, edges_gdf_2 = ox.graph_to_gdfs(ox.simplify_graph(G2))
错误原因
问题源于无向图转换后的边属性类型异常:调用G.to_undirected()后,部分原本为单一值的边属性(如oneway)会被转为列表类型。而ox.simplify_graph在处理属性时,会尝试将属性值存入集合(set(path_attributes[attr])),但列表是不可哈希类型,直接存入集合就会触发该TypeError。
解决方法
方案1:放弃无向图转换(如果业务允许)
直接去掉G.to_undirected(),保持原图的有向性,重建后即可正常简化:
import shapely import osmnx as ox poly = shapely.from_wkt("POLYGON((9.493474960327147 51.228210969202365," "9.493346214294432 51.223359875812804," "9.498442411422728 51.22356145497176," "9.498571157455443 51.228036284963565," "9.493474960327147 51.228210969202365))") G = ox.graph_from_polygon(poly, network_type="drive") nodes_gdf, edges_gdf = ox.graph_to_gdfs(G) # 移除to_undirected() G2 = ox.graph_from_gdfs(gdf_nodes=nodes_gdf, gdf_edges=edges_gdf) nodes_gdf_2, edges_gdf_2 = ox.graph_to_gdfs(ox.simplify_graph(G2))
方案2:处理无向图的列表类型属性(如果必须使用无向图)
在重建图之前,将边属性中的列表类型转换为可哈希的单一值。以oneway为例,取列表第一个元素(或根据业务逻辑合并):
import shapely import osmnx as ox poly = shapely.from_wkt("POLYGON((9.493474960327147 51.228210969202365," "9.493346214294432 51.223359875812804," "9.498442411422728 51.22356145497176," "9.498571157455443 51.228036284963565," "9.493474960327147 51.228210969202365))") G = ox.graph_from_polygon(poly, network_type="drive") nodes_gdf, edges_gdf = ox.graph_to_gdfs(G.to_undirected()) # 处理列表类型的边属性 edges_gdf['oneway'] = edges_gdf['oneway'].apply(lambda x: x[0] if isinstance(x, list) else x) # 其他可能转为列表的属性(如lanes、access等)需同理处理 # edges_gdf['lanes'] = edges_gdf['lanes'].apply(lambda x: x[0] if isinstance(x, list) else x) G2 = ox.graph_from_gdfs(gdf_nodes=nodes_gdf, gdf_edges=edges_gdf) nodes_gdf_2, edges_gdf_2 = ox.graph_to_gdfs(ox.simplify_graph(G2))
方案3:无向图转换时禁用属性列表化
调用to_undirected()时指定reciprocal=False,避免属性被转为列表,但这会改变无向化的逻辑(不会添加反向边),需根据需求选择:
nodes_gdf, edges_gdf = ox.graph_to_gdfs(G.to_undirected(reciprocal=False))
内容的提问来源于stack exchange,提问作者mcsoini
相关产品推荐
相关产品推荐

